From e97bad8ab8835c433c3d4e1114bf99284c508a4b Mon Sep 17 00:00:00 2001 From: Adi Azulay Date: Thu, 18 Feb 2021 09:56:05 -0800 Subject: [PATCH 1/3] bump to v0.3.5 (#1196) * update usb native * update changelog * fix ref tag for publishing * fix ref tag for publishing * change build to check version env var * fix version spelling * add {} to if in publish * change version check to regex * fix formatting * change to multiline run * add echo for ISPRODUCTION * add missing s to outputs * remove debugging echo --- .github/workflows/build.yml | 8 ++- CHANGELOG.md | 7 ++ package-lock.json | 126 ++++++++++++++++++++++-------------- package.json | 6 +- 4 files changed, 94 insertions(+), 53 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c2598d3d..47a37649 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -103,6 +103,12 @@ jobs: tag: ${{ github.ref }} overwrite: true file_glob: true + - name: check for production tag + id: check-version + run: | + if [[ ${{ env.VERSION }} =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo ::set-output name=ISPRODUCTION::true + fi - name: publish - if: github.ref == 'refs/tags/[0-9].[0-9].[0-9]' + if: steps.check-version.outputs.ISPRODUCTION == 'true' run: vsce publish -p ${{ secrets.VSCE_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 858ce039..9c9f877d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Change Log All notable changes to this project will be documented in this file. +## Version 0.3.5 + +- Release date: November 22, 2020 + +### Fixes +- Update to node-usb-native 0.0.19 + ## Version 0.3.4 - Release date: November 22, 2020 diff --git a/package-lock.json b/package-lock.json index d72659ed..8229e3f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "vscode-arduino", - "version": "0.3.3", + "version": "0.3.5", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -84,9 +84,9 @@ }, "dependencies": { "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "requires": { "ms": "2.1.2" } @@ -108,9 +108,9 @@ }, "dependencies": { "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "requires": { "ms": "2.1.2" } @@ -123,22 +123,22 @@ } }, "@serialport/bindings": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.0.2.tgz", - "integrity": "sha512-kQ3co4aGwwbUqkRdJ7UfdlbLB5dUQwNfSglexC8iv65D5HXfjSBR1bE0XUH8PH/v/6Dh6CSnwf6OP0I3H5vMWQ==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.0.4.tgz", + "integrity": "sha512-6dlE1vm5c1xk667f1Zm7D+msbHJ9jdnUr9l8DResKpj2iCBzbCNsW+yCYq26WxzXWc1L2HUaS3/aL+k0wm5amg==", "requires": { "@serialport/binding-abstract": "^9.0.2", "@serialport/parser-readline": "^9.0.1", "bindings": "^1.5.0", - "debug": "^4.1.1", - "nan": "^2.14.1", - "prebuild-install": "^5.3.5" + "debug": "^4.3.1", + "nan": "^2.14.2", + "prebuild-install": "^6.0.0" }, "dependencies": { "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "requires": { "ms": "2.1.2" } @@ -170,6 +170,11 @@ "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.0.1.tgz", "integrity": "sha512-+oaSl5zEu47OlrRiF5p5tn2qgGqYuhVcE+NI+Pv4E1xsNB/A0fFxxMv/8XUw466CRLEJ5IESIB9qbFvKE6ltaQ==" }, + "@serialport/parser-inter-byte-timeout": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.0.1.tgz", + "integrity": "sha512-lFflcUflcP5SF4vLIixAKs1xUI/wfOzCv1Xq78VbPOBlIjZ6ny9lQ6g7cMPR/sB/M1BHwGcdX7CEr90pe3kkog==" + }, "@serialport/parser-readline": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.0.1.tgz", @@ -197,9 +202,9 @@ }, "dependencies": { "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "requires": { "ms": "2.1.2" } @@ -1043,9 +1048,9 @@ } }, "bl": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz", - "integrity": "sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.4.tgz", + "integrity": "sha512-7tdr4EpSd7jJ6tuQ21vu2ke8w7pNEstzj1O8wwq6sNNzO3UDi5MA8Gny/gquCj7r2C6fHudg8tKRGyjRgmvNxQ==", "requires": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -1255,9 +1260,9 @@ } }, "buffer": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.0.tgz", - "integrity": "sha512-cd+5r1VLBwUqTrmnzW+D7ABkJUM6mr7uv1dv+6jRw4Rcl7tFIFHDqHPL98LhpGFn3dbAt3gtLxtrWp4m1kFrqg==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "requires": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -6297,9 +6302,9 @@ "dev": true }, "node-abi": { - "version": "2.19.1", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.19.1.tgz", - "integrity": "sha512-HbtmIuByq44yhAzK7b9j/FelKlHYISKQn0mtvcBrU5QBkhoCMp5bu8Hv5AI34DcKfOAcJBcOEMwLlwO62FFu9A==", + "version": "2.19.3", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.19.3.tgz", + "integrity": "sha512-9xZrlyfvKhWme2EXFKQhZRp1yNWT/uI1luYPr3sFl+H4keYY4xR+1jO7mvTTijIsHf1M+QDe9uWuKeEpLInIlg==", "requires": { "semver": "^5.4.1" } @@ -6384,12 +6389,12 @@ } }, "node-usb-native": { - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/node-usb-native/-/node-usb-native-0.0.18.tgz", - "integrity": "sha512-z2yGYM1MURtCdKsLZkN7X3b8ERNRQeMBLZ+7HEy/2PIJz76tVkrOqU+lvQtK2LkuLBtsIgsArjOzzrFdoYxijw==", + "version": "0.0.19", + "resolved": "https://registry.npmjs.org/node-usb-native/-/node-usb-native-0.0.19.tgz", + "integrity": "sha512-nW5UvIN4aSkWxaX+7b+3hwQkjZ++MtnWLLskp4r+X73KGW2vLm10scyGb1Na7A5Nij0Ey/qsYMZo5j4PLM65WA==", "requires": { "glob": "^7.1.6", - "serialport": "^9.0.1", + "serialport": "^9.0.4", "usb-detection": "^4.10.0" } }, @@ -6942,9 +6947,9 @@ "dev": true }, "prebuild-install": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.6.tgz", - "integrity": "sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.0.0.tgz", + "integrity": "sha512-h2ZJ1PXHKWZpp1caLw0oX9sagVpL2YTk+ZwInQbQ3QqNd4J03O6MpFNmMTJlkfgPENWqe5kP0WjQLqz5OjLfsw==", "requires": { "detect-libc": "^1.0.3", "expand-template": "^2.0.3", @@ -7531,15 +7536,16 @@ } }, "serialport": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.0.2.tgz", - "integrity": "sha512-N++EVrc2F3kUJ6aCE6BLxHwTrelFAZM3LFw4lo8TV0fDtfrwTc3+aoDpSsvfQg3DxrRf3shCtA6WYEH4g8kapw==", + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.0.6.tgz", + "integrity": "sha512-T9eY4HFzQij0Hd/RsPcZySdeuAqzV5iGICHz8FXUSKVn2SvGT5zjfz/H+pRwI86k+3iFVOyddEyy8gbVNVbW7A==", "requires": { "@serialport/binding-mock": "^9.0.2", - "@serialport/bindings": "^9.0.2", + "@serialport/bindings": "^9.0.4", "@serialport/parser-byte-length": "^9.0.1", "@serialport/parser-cctalk": "^9.0.1", "@serialport/parser-delimiter": "^9.0.1", + "@serialport/parser-inter-byte-timeout": "^9.0.1", "@serialport/parser-readline": "^9.0.1", "@serialport/parser-ready": "^9.0.1", "@serialport/parser-regex": "^9.0.1", @@ -7548,9 +7554,9 @@ }, "dependencies": { "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "requires": { "ms": "2.1.2" } @@ -8200,20 +8206,20 @@ } }, "tar-fs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.0.tgz", - "integrity": "sha512-9uW5iDvrIMCVpvasdFHW0wJPez0K4JnMZtsuIeDI7HyMGJNxmDZDOCQROr7lXyS+iL/QMpj07qcjGYTSdRFXUg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", "requires": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", - "tar-stream": "^2.0.0" + "tar-stream": "^2.1.4" } }, "tar-stream": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.4.tgz", - "integrity": "sha512-o3pS2zlG4gxr67GmFYBLlq+dM8gyRGUOvsrHclSkvtVtQbjV0s/+ZE8OpICbaj8clrX3tjeHngYGP7rweaBnuw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "requires": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", @@ -8726,6 +8732,28 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz", "integrity": "sha1-YZegldX7a1folC9v1+qtY6CclFI=" + }, + "prebuild-install": { + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.6.tgz", + "integrity": "sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==", + "requires": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.7.0", + "noop-logger": "^0.1.1", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0", + "which-pm-runs": "^1.0.0" + } } } }, diff --git a/package.json b/package.json index 0d526c16..6629987b 100644 --- a/package.json +++ b/package.json @@ -2,12 +2,12 @@ "name": "vscode-arduino", "displayName": "Arduino", "description": "Arduino for Visual Studio Code", - "version": "0.3.4", + "version": "0.3.5", "publisher": "vsciot-vscode", "aiKey": "83dd2c27-6594-41d3-85a9-bdb22070eb42", "preview": true, "engines": { - "vscode": "^1.50.0" + "vscode": "^1.53.0" }, "icon": "images/arduino.png", "license": "SEE LICENSE IN LICENSE.txt", @@ -582,7 +582,7 @@ "glob": "^7.1.1", "iconv-lite": "^0.4.18", "impor": "^0.1.1", - "node-usb-native": "^0.0.18", + "node-usb-native": "^0.0.19", "properties": "^1.2.1", "uuid": "^3.0.1", "vscode-extension-telemetry": "0.1.6", From 3bb7b14f1dcf803180e6a16773dccebc9ced6725 Mon Sep 17 00:00:00 2001 From: Adi Azulay Date: Mon, 22 Mar 2021 13:38:49 -0700 Subject: [PATCH 2/3] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 57c8d2dff5637a9cdcea0c2f0188c22e5a2cce3e Author: Adi Azulay Date: Mon Mar 22 13:00:21 2021 -0700 update changelog commit 6e659974165a65fd5a7fe64c19b20b516e890b39 Author: Adi Azulay Date: Mon Mar 22 12:49:56 2021 -0700 bump to v0.4.0 commit 6d63a018cf2f26dbc6377ab3d38f5a99a5d8544a Author: Adi Azulay Date: Tue Mar 9 08:54:05 2021 -0800 update version commit ed886ad7d8c265643aeb90e172c8b84351baa251 Merge: 6ecfc55 9ca2400 Author: Adi Azulay Date: Mon Mar 8 14:01:55 2021 -0800 Merge branch 'develop' into pre-release-v0.4.0 commit 9ca24007f119ee46a73f27dec7f2d5901ccb5749 Author: Adi Azulay Date: Fri Mar 5 09:58:10 2021 -0800 remove -MMD from complier args for intellisesne (#1208) commit 6ecfc55c3adc6fd484353d95750436de3171e685 Author: Adi Azulay Date: Thu Feb 18 11:27:45 2021 -0800 update version in package commit 11265813085dacc45f02e3ae6bf978620c6bff30 Author: Adi Azulay Date: Thu Feb 18 11:07:59 2021 -0800 update readme commit 5571e5249260c80ecc8cbf8ca6d4d55f0761ae48 Author: Adi Azulay Date: Thu Feb 18 10:52:24 2021 -0800 update package-lock commit 0b60f1fcd9f632f389882b62495865416adf82ca Merge: e044711 e97bad8 Author: Adi Azulay Date: Thu Feb 18 09:59:26 2021 -0800 Merge branch 'master' into pre-release-v0.4.0 commit e044711696797428210b18a67f693af70efdc513 Merge: 739aa95 5f4c400 Author: Adi Azulay Date: Thu Feb 4 14:32:52 2021 -0800 Merge branch 'develop' of https://github.com/microsoft/vscode-arduino into pre-release-v0.4.0 commit 739aa956b1ab2bd3d90cd753008496c97ff71176 Author: Adi Azulay Date: Thu Feb 4 14:21:55 2021 -0800 pre release v0.4.0 commit 5f4c400251c499cbcc60d8aa1c1285073088a5c8 Merge: b7094ba 595def8 Author: Adi Azulay Date: Thu Feb 4 11:53:29 2021 -0800 Merge branch 'master' into develop commit b7094ba74e2a15773193e0bdbd59f0c27598a575 Author: Adi Azulay Date: Fri Jan 22 14:56:07 2021 -0800 remove IntelliSense Auto branch notes commit b0375c8c9f9ec0551bd4fad789dd42be9083933b Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed Jan 20 09:45:43 2021 -0800 Bump ini from 1.3.5 to 1.3.8 (#1159) Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.8. - [Release notes](https://github.com/isaacs/ini/releases) - [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.8) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Adi Azulay commit f80b38f6b3d46918fdefb177429e89d85e8e76da Author: Jason Tranchida Date: Tue Jan 19 16:41:36 2021 -0800 Populate the list of programmers by parsing programmers.txt for each package (#1129) * Improved handling of programmer selection - Selected programmer is now saved to and loaded from the arduino.json file - Arduino.json is monitored for changes, and changing file will update selected programmer & ui - Programmer selection UI now shows both the friendly name of the programmer, as well as the arduino name - Minor fix to deviceContexts to fire change events after all states are modified - Layed groundwork to support querying list of programmers for the current board from arduino toolchain * Parse the list of programmers from packages * Tests for parsing programmers * Show board specific list of programmers when selecting Populate the selected programmer and it's display name using list of programmers provided by BoardManager. When selecting programmer, only present the user a list of programmers relevant to the current board. * Initial set of tests for ProgrammerManager * add support for cli * fix hardcoded package name for programmers * adds programmer.key back to support arduino IDE * fix handeling of programmer name in ide and cli Co-authored-by: Adi Azulay commit 8bb1130a7b6bbf12fd4cb1bd912a7b4871ad20c6 Author: Adi Azulay Date: Tue Jan 19 12:16:15 2021 -0800 fix missing " commit a717e5b4160c6d3d78eb91f1bf0155013a18247a Author: Adi Azulay Date: Tue Jan 19 12:11:25 2021 -0800 update travis commit 9d1899ef4f140e6e19a74c47dcafefeac39205df Author: Adi Azulay Date: Tue Jan 12 12:25:51 2021 -0800 remove redundant prebuild check commit 7ac331f2c60af3a2eb1a0cff16e370c5df48bb2e Author: Adi Azulay Date: Tue Jan 12 12:08:33 2021 -0800 fix verbose setting and cli programmer upload commit b91a5cab3cd6520592bc06db33e2bd0ca6b126e5 Author: Adi Azulay Date: Thu Dec 10 16:41:17 2020 -0500 fix cli analyze mode commit 2e763c84f53ab8f0fbeda1bde13b5a93222b77cf Author: Adi Azulay Date: Thu Dec 10 15:53:53 2020 -0500 add support for cli commit b5360b5e8b3b44ff7ff1aaeeee590e92bd9616be Author: Håkon Løvdal Date: Thu Jan 7 00:39:08 2021 +0100 Remove arrow-head anti-pattern commit 0356bb72375b2f5771d250092fcac6283106d8c8 Author: Håkon Løvdal Date: Wed Jan 6 23:03:06 2021 +0100 Join args.push statements commit b97a740444dab1550f6738f75bfb439a3650866f Author: Håkon Løvdal Date: Wed Jan 6 22:38:23 2021 +0100 Replace "upload" with "compile --upload" commit e591480259aa1974910ef12fd707d8641864cd2c Author: Håkon Løvdal Date: Wed Jan 6 21:25:59 2021 +0100 Reverse and merge tests commit 5a49b972164128f5948296efa70c610f25271837 Author: Håkon Løvdal Date: Tue Jan 5 22:23:21 2021 +0100 Remove compile argument and expand BuildMode with CliUpload and CliUploadProgrammer commit 8b838738d88933042cbeefcf7dda927af24e4595 Author: Håkon Løvdal Date: Tue Jan 5 23:34:25 2021 +0100 Consolidate all boardDescriptor argument pushing commit a6512a4c2e431dc3cea9d47b89dc8a7ef98f6df5 Author: Håkon Løvdal Date: Mon Jan 4 21:48:51 2021 +0100 Move the _build to the end and make private commit c2ab5775e39154cd84051d7dddf50c2c1f4f09cd Author: Uli Franke Date: Sat Feb 29 14:39:38 2020 +0100 Updated log, additional stuff and beers commit 8a491ed6ddd1df40ce66f8029f53088bde448bcc Author: Uli Franke Date: Sat Feb 29 13:50:28 2020 +0100 Fixed security issue * Web-server for library-, board-manager etc. was not listening on localhost but on the machine's main interface * Web-server wasn't launched asynchronously what can cause problems * Port was stored redundantly in webserver class Addresses #966 commit 5f32221c20bb48afd86040494e1ca1214371a709 Author: Uli Franke Date: Sat Feb 29 12:15:17 2020 +0100 Add and document buildPreferences setting * Validator for `buildPreferences` * Documentation for `buildPreferences` commit 9543ba7ebf842e3c31eb9f7ad596be0c575ce0db Author: Uli Franke Date: Sat Feb 29 11:24:35 2020 +0100 Support for Arduino preferences in `arduino.json`. These preferences are applied during any build and can be used to set custom compiler flags and defines for instance. Addresses #975 commit f9cd3c5c9c2229bc2ee2b88f8ef8c2b935661c51 Author: Uli Franke Date: Sat Feb 29 07:55:37 2020 +0100 Fix too early initialization of cocopa * Fixed bug with build: initializing cocopa too early (was failing if sketch wasn't initialized) * More info in error message for uncaught exception during build cleanup * Note on output path preparation which seems to be a bit wonky commit 48c4c64fe3de31a0d4b76ee0f07136ee1d1ef2d3 Author: Uli Franke Date: Sat Feb 29 01:04:29 2020 +0100 Updated log, status and beers commit 95f5a181ec43fe829aa49cf1ea3c52ccc6eeb568 Author: Uli Franke Date: Sat Feb 29 00:32:05 2020 +0100 Documentation for pre-/post-build commands and their environment variables commit f85a78347e59d53ab3f944f823842e1dafcf29cd Author: Uli Franke Date: Fri Feb 28 23:57:08 2020 +0100 Full cmd support for pre-/post-build commands on Windows Addresses #786 commit 2af8f11af5ac41adbcf654d3b8437b01d9830587 Author: Uli Franke Date: Fri Feb 28 23:19:56 2020 +0100 Pre-/post-build command improvements * Full bash syntax support for pre-/post-build commands on UNIX systems * Environment variables for pre-/post-build commands which give the user access to several build process parameters like the sketch, the output directory, serial port, build mode (verify, upload, analyze, ...), board type and workspace path Addresses #786 commit d3bcf6e19f707333ffb586400a425b48ad7268b8 Author: Uli Franke Date: Fri Feb 28 21:07:50 2020 +0100 Logging and post-build commands * Error logging for exceptions during build cleanup * Compacted log message filter regexes * Moved pre-build command after initialization of the output folder in case this command somehow wants to operate on it somehow * Better error message handling when post-build command fails * Forwarding post-build command error commit 7c1104c7011046ae0b490965e2be7c99ed7b0e4c Author: Uli Franke Date: Fri Feb 28 15:29:32 2020 +0100 Section which outlines additional features this branch addresses commit 2b84aa853f94c5ec498e75547a792d75f6e3730b Author: Uli Franke Date: Fri Feb 28 15:28:21 2020 +0100 C++ standard is now parsed from compiler arguments Plus: Moved some methods to cocopa and got rid of the typed-promisify dependency commit f6c3b2c66f5c350b2cb1570c6becf5a4d6c2feb2 Author: Uli Franke Date: Thu Feb 27 22:49:54 2020 +0100 Added post build command support * Added post build command support * Added validator for both pre and post build (former was missing) Yet to be decided: Solution for analysis run: with or without pre/post build? Addresses #786 commit 7039ea8de9204b6f2241fcf1ca038bb3559180d2 Author: Uli Franke Date: Thu Feb 27 21:21:33 2020 +0100 IntelliSense auto gen respected global and project specific dis-/enable flags for analyze only. Now these flags have the same effect during regular builds. commit deaa18a231cc494580c0ee655f59127200666e4d Author: Uli Franke Date: Thu Feb 27 21:02:49 2020 +0100 Collapsing multiple consecutive newlines into a single newline for non verbose build log commit 30210dc336910c9b748045cd4435d7fd1e003369 Author: Uli Franke Date: Thu Feb 27 19:47:44 2020 +0100 Make upload verbosity be conditional and extend filtering * Building always verbosely but upload only verbosely when requested * Filtering of spurious messages now with regex list and for all platforms commit fed508f4b7b24032f937ca81b4f1eeb0f009202e Author: Uli Franke Date: Thu Feb 27 19:44:35 2020 +0100 Filter out invalid include directories * Filtering out invalid include directories (discovered when compiling for ESP8266) * Compacted IntelliSense message and hint to manual build into a single line commit 194dc920f20057330e3f90fc2b89fe29f43a6c23 Author: Uli Franke Date: Thu Feb 27 18:40:27 2020 +0100 Fixed exception which occurs if one of the include directories doesn't exists and we try to search it for Arduino.h commit 70d323d07ef382e8894f521aee80e1d835b5b2ff Author: Uli Franke Date: Thu Feb 27 18:36:01 2020 +0100 Fixed bug in board.ts: Conceptual flaw when checking if configuration option is valid commit 314d4a8648ea509ebcad7d7e904f38ad1e6259ac Author: Uli Franke Date: Thu Feb 27 16:11:33 2020 +0100 Build/analysis logging improvements commit b489a8fdec21a8c8ff9eeca26731d7e12657ec14 Author: Uli Franke Date: Thu Feb 27 14:03:58 2020 +0100 Run IntelliSense analysis for every build * Run IntelliSense analysis for every build * Added global enum for log level commit 88e544a0e6c649fc3cae31dc7b809f4922981ee5 Author: Uli Franke Date: Wed Feb 26 16:36:40 2020 +0100 Added link to alpha releases to top of document commit 15fd705a825fccc6ed0e15ba4269372700a72d4a Author: Uli Franke Date: Wed Feb 26 16:21:12 2020 +0100 Updated beers commit 27d9cac9bcfaccd2e5bf4329e29685f869c8241e Author: Uli Franke Date: Wed Feb 26 16:15:06 2020 +0100 Final pull request dependency style for cocopa commit e7f7d055c92bc141cfb4f2853101ee20d4e1466a Author: Uli Franke Date: Wed Feb 26 16:14:15 2020 +0100 Updated log commit 764d21ebb25125b63828422a9dec60b5b46417eb Author: Uli Franke Date: Wed Feb 26 15:57:00 2020 +0100 Refined some documentation comment commit deecdf276d1f1287e9dea009c2a5f03010d570cf Author: Uli Franke Date: Wed Feb 26 15:48:54 2020 +0100 Changed Serial.updatePortListStatus to make use of optional argument to eliminate updatePortListStatus(null) calls commit cdf9f342c349fa2549b0a5eb103d53408ee526d7 Author: Uli Franke Date: Wed Feb 26 15:46:40 2020 +0100 Added/reviewed some notes commit 42025082dbad9bac813776d142f3d28466a7cd41 Author: Uli Franke Date: Wed Feb 26 15:28:52 2020 +0100 Reworked util.spawn to mergable version commit d408686c1d3dff04da6396d1bb9218af0904be4b Author: Uli Franke Date: Wed Feb 26 14:22:52 2020 +0100 Removed IS-REMOVE code * Removed code marked with `IS-REMOVE` previously * Added constant for the `c_cpp_properties.json`-configuration managed by vscode-arduino * Removed code rendered dead by the previous removal commit 31e530c72c8b1c75d870dc0879fb47571f537f6e Author: Uli Franke Date: Tue Feb 25 17:16:15 2020 +0100 Updated cocopa to version 0.0.12 * Implemented and tested support for `.cpp`-sketches. * Done implementing the most relevant unit tests in cocopa. * Two independent alpha testers confirmed proper working of the previous alpha releases. * Updated to the latest revision of cocopa. commit b5714b6fa8243697907652b6b697ec01f7449b23 Author: Uli Franke Date: Sun Feb 23 18:34:33 2020 +0100 Updated log and beers commit f2a5307279b5d45dbf5736daf408366c4c6522ce Author: Uli Franke Date: Sun Feb 23 18:26:31 2020 +0100 Forceinclude Arduino.h * Added message to end of each build to inform user how to update the IntelliSense configuration * The magic now searches all identified include paths for the Arduino core include file (aka Arduino.h) and adds it as forced include - most users expect Arduino core functionality to work without having to include this header. Added typed-promisify to dependencies since I made use of it in the new code for better readability. * Conclude is now asynchronous * Updated branch status and added new future task * Bumped cocopa version to 0.0.10 commit b7effbc91110c2f34e4382fb95ac58277d573e6c Author: Uli Franke Date: Sat Feb 22 23:29:15 2020 +0100 Updated log * Updated branch log and beers commit 5fe6dbc44ec7e53f2ae55562e301280251f0330c Author: Uli Franke Date: Sat Feb 22 23:17:59 2020 +0100 IntelliSense config generator * Now normalizes generated include paths * Bumped cocopa to 0.0.9 commit 4238e12089560110cf682c25dac3c12106299259 Author: Uli Franke Date: Sat Feb 22 20:33:16 2020 +0100 Updated to latest cocopa which features X-platform support and better lexer commit e6c10cd02fd64cd4d9e45189c3c9e6a0e732e96f Author: Uli Franke Date: Sat Feb 22 20:24:30 2020 +0100 Updated log and beers commit 2d52e526b85b70c38bc60b3aea4c1fe460e9a036 Author: Uli Franke Date: Sat Feb 22 14:25:22 2020 +0100 Fixed handling of invalid manual configurations. Improved code locality for board configuration manipulation and fixed a race condition with fine grained event handling. Details: Added missing checks when board configurations are loaded from the configuration file: * Up to now vscode-arduino blindly loaded any board configuration from `arduino.json` even if this would result in invalid board configurations which in turn lead to compilation (verify, upload) failure. * Up to now this state couldn't be recovered by simply removing the offending configuration from the configuration file. Even worse: it stored the wrong configuration in between board changes. To reproduce the bug in 0.2.29 1. Select Arduino Nano with the *Arduino Board Configuration* 2. Set configuration in `arduino.json` to `cpu=cray2` and save 3. Verify -> fails 4. Switch board to Arduino Uno 5. Switch back to Arduino Nano: The wrong configuration is back and now the user can't even select another (correct) configuration from the *Arduino Board Configuration* window 6. Delete the wrong configuration and save -> verify still fails `vscode-arduino` does not fall back to a default configuration. The user has now two options: find the correct configuration by himself and set it within arduino.json. Very experienced users could probably accomplish that. Everone else can just restart vscode. I corrected that by enhancing IBoard.loadConfig and IBoard.updateConfig member functions to * check for proper formatting of the config string loaded from `arduino.json` * check if the configuration IDs and the option IDs are valid If any of the above fails, the functions bail out and return the error. The board manager then loads a default configuration and issues a warning, that the configuration is invalid. This way the user gets the chance to fix her/his configuration but gets informed at the same time, that a different configuration than the intended is loaded (prevents surprises). This situation is only relevant, when users start fiddling with the configuration values in `arduino.json`. As long as they just set the board and the configurations from within the *Arduino Board Configuration Window* nothing bad can happen. But now custom configurations are handled in a cleaner way. The DeviceContext's board configuration was set in board.ts and boardManager.ts in different places - even when it was loaded after a DeviceContext's configuration update event which is prone to infinite loops. This has been resolved and it's not re-written/re-set during loading a configuration on change. This is valid for board manager's updateStatusBar function which fiddled with the board and the configuration. Now updateStatusBar really just updates the status bar. And it isn't necessary to call it from outside the board manager anymore due to proper event handling which identifies the situations during which the status bar has to be updated. Therefore this member is now private. In board manager itself operations that affect device context and current board now happen only within doChangeBoardType and the event handlers of DeviceContext callbacks onDeviceContextConfigurationChange and onDeviceContextBoardChange. This prevents the accidental creation of infinite event loops, makes the code more understandable, maintainable and therefore resilient against future bugs. commit 640f269725d46d172c6bf93b39ac3066a2ad7e60 Author: Uli Franke Date: Fri Feb 21 21:45:52 2020 +0100 Removed obsolete doc folder as all this is now part of cocopa commit 98dbc0d35246cff5201b04f5ae2abb4e733f628f Author: Uli Franke Date: Fri Feb 21 00:40:16 2020 +0100 Updated log, status and beers commit 01e92e9d6158fad87e1d8d3c8e081e494188c5b3 Author: Uli Franke Date: Wed Feb 19 23:59:01 2020 +0100 Added "some" additional issues -- currently I've found 28! commit 5fd1a2706f1f1d6ba37fc9bbbc668f91aef2ddd7 Author: Uli Franke Date: Wed Feb 19 23:01:36 2020 +0100 Updated log and beers. commit c15dc08fa617b34e5b00643ce14d0ea8e827fc9d Author: Uli Franke Date: Wed Feb 19 22:45:54 2020 +0100 IntelliSense auto-analysis integration * Reworked DeviceContext for fine grained event generation on settings change * Added dedicated settings classes which allows for the latter * Changed board manager and serial monitor to used the new fine grained events instead of the "something changed event" - which makes the code marginally more efficient * Implemented an analysis manager which takes care of analysis requests generated by settings change events and makes sure that analysis builds don't interfere with regular builds * Adapted the build infrastructure within ArduinoApp such that it allows for the above * Removed the global build guard and moved it to ArduinoApp (there is a corner case though for programmer selection within extension.ts which I marked with a TODO * Fixed some linting issues but did not lint most of the stuff committed here - this will be part of a later commit * I left notes here and there where I saw things which should/could be improved/changed * Removed the try/catch guards from the build invocations within extension.ts since exceptions are handled within the build function itself * Changed the project setting parameter for the IntelliSense setup to reflect its workings better commit 548c714b1369630238af3306e40f012e43dc45a5 Author: Uli Franke Date: Wed Feb 19 19:36:36 2020 +0100 Updated and completed documentation of the current state within README.md * Updated project log and status commit 59bad214e52ae13f1564db9e34ee58c1af231927 Author: Uli Franke Date: Wed Feb 19 16:18:15 2020 +0100 Updated project log and status commit cabeed61fb077a9154dd926dd0ca608f806a213f Author: Uli Franke Date: Tue Feb 18 20:12:07 2020 +0100 Updated log and issues * Added/documented all known related issues * Updated log * Updated and extended status * General brushing of structure and text commit d6c7b5ac74131b7d5614745bfd7536c9031a249c Author: Uli Franke Date: Tue Feb 18 18:21:21 2020 +0100 New classes which will improve the device settings management and event handling. To be integrated with one of the next commits. commit d712a94b21f85284a27a0a1637a45f7d74b77dd1 Author: Uli Franke Date: Tue Feb 18 13:26:09 2020 +0100 Don't use hard coded paths when possible. commit 6c1fe68b34cd45e1055d063f09f8ce5e5bbfab1a Author: Uli Franke Date: Tue Feb 18 01:54:11 2020 +0100 Updated project log commit 41bcd445013571bdf824a7d6b1d8d0cf22ec61dd Author: Uli Franke Date: Mon Feb 17 16:38:12 2020 +0100 Disabled and marked all previous implementations of IntelliSense support for later removal using `IS-REMOVE` commit 3418458f72f0df6b79c42bb806491f8497f02a2d Author: Håkon Løvdal Date: Fri Dec 11 23:25:51 2020 +0100 Fix whitespace commit f914a4b3270e7d3c3e6f256e3b5cca471bc36ce5 Author: Håkon Løvdal Date: Fri Dec 11 23:18:01 2020 +0100 Add arduino.rebuildIntelliSenseConfig commit 216e1b8ec2a7a748b388bb8ffe2fdd226539204f Author: Håkon Løvdal Date: Fri Dec 11 23:14:26 2020 +0100 Merge build and verify commit 2a2db50081b24750b7e84f8bed80b28429c08092 Author: Håkon Løvdal Date: Fri Dec 11 23:12:03 2020 +0100 Make build and verify identical commit 2039739b749095e5324ce3e63e8d0f2a44e9320e Author: Håkon Løvdal Date: Fri Dec 11 22:53:33 2020 +0100 Make build return boolean commit fef2db0447df7a6a20c4cc68fceecc33688862a4 Author: Håkon Løvdal Date: Fri Dec 11 18:07:15 2020 +0100 Use cocopa and add Analyze build mode commit 0b2b77ac34cc7dc78dc56b03a70d02581b3dbdb8 Author: Håkon Løvdal Date: Fri Dec 11 00:27:21 2020 +0100 Rename output to buildDir commit 335d80aafcd42cea7e063f19c4e6b87e4e1c9733 Author: Håkon Løvdal Date: Fri Dec 11 00:10:17 2020 +0100 Add stdoutCallback expression commit 4aa7ddcac2ceae01059b6f368d0d2e5572d746d7 Author: Håkon Løvdal Date: Thu Dec 10 23:52:29 2020 +0100 Add buildMode argument to verify commit e4a70b02b1c600b47acb9df468dfdcda6704ec4d Author: Håkon Løvdal Date: Thu Dec 10 23:39:12 2020 +0100 Merge upload and uploadUsingProgrammer into one build function commit a14f777f7d8cdf6b394e678b33ec7d4f3a7ca394 Author: Håkon Løvdal Date: Thu Dec 10 23:36:46 2020 +0100 Make upload and uploadUsingProgrammer identical commit 76c74cf99520c0236d988e0be9c5ca695bde2afa Author: Håkon Løvdal Date: Thu Dec 10 23:26:46 2020 +0100 Add buildMode argument to upload and uploadUsingProgrammer commit 86719a36a65a9c93116a5fe325de68180bb604b7 Author: Håkon Løvdal Date: Tue Jan 5 23:03:58 2021 +0100 Spelling correction commit cd9365b34ac84049a9082742eff2ccd2d11d044e Author: Håkon Løvdal Date: Thu Dec 10 23:00:46 2020 +0100 Move selectProgrammer down commit e03dc382a5a74c36236275d4d54ced439acfaada Author: Håkon Løvdal Date: Thu Dec 10 22:26:39 2020 +0100 Move arg buildup earlier in functions commit 88bed5e34ef42caa251507649ea5f57618567b27 Author: Håkon Løvdal Date: Thu Dec 10 21:57:40 2020 +0100 Inline and move appPath later commit 82270144542ed9620de7bb524f35f7b995300a30 Author: Håkon Løvdal Date: Thu Dec 10 21:52:59 2020 +0100 Add selectSerial expression commit 990c1a16a4da489cd1b7c6a00ae337d09d4e8b6a Author: Håkon Løvdal Date: Thu Dec 10 21:36:40 2020 +0100 Add cleanup expression commit 0678c9af5bed34465c389b9491541245aa955869 Author: Håkon Løvdal Date: Thu Dec 10 21:09:50 2020 +0100 Unify exit error message commit b28f574dde43c89160d49377ba902d83bb96a170 Author: Håkon Løvdal Date: Thu Dec 10 20:59:19 2020 +0100 Unify util.spawn invocation commit a6968e07dd1ce1c782c192f540851c5d2ed8b3ea Author: Håkon Løvdal Date: Thu Dec 10 20:45:53 2020 +0100 Introduce verbose variable commit 3879639377d7948b385a1ffb7038021769b58e6c Author: Håkon Løvdal Date: Thu Dec 10 20:21:12 2020 +0100 Move args variable till top of upload, uploadUsingProgrammer and verify commit dd308accb7bd38228b6165c91f4b6ccd06121be6 Author: Håkon Løvdal Date: Tue Dec 8 22:40:05 2020 +0100 Rename verifyResult to success commit e4c13d022f966f34490688dc6e73bcf8d8c87056 Author: Håkon Løvdal Date: Tue Dec 8 22:24:21 2020 +0100 Rename Logger to logger commit a5d4695d5201dfea5e7e69c67ba1318cbc07332a Author: Uli Franke Date: Sat Feb 15 20:49:13 2020 +0100 Updated branch notes -- documented changes not committed though. commit 5945d8dd0c1aa4552769b84b018adab84c285404 Author: Uli Franke Date: Sat Feb 15 12:47:31 2020 +0100 Updated beer money log commit 56c963420f33222f2cba49d33ab15ef601cb3571 Author: Uli Franke Date: Wed Feb 12 18:12:43 2020 +0100 Note how to run vscode without having gulp on your user path commit 4341261e91981a2687beb70b8583277a8b5d5e7e Author: Uli Franke Date: Wed Feb 12 17:53:28 2020 +0100 More on beta testing, added link to chat room commit e80a338642eb54bf2eb08f64167ec2a7ffcf584e Author: Uli Franke Date: Wed Feb 12 17:00:26 2020 +0100 Added instructions how to run development code commit 6a42d3f3d94dd44cda9f647bf17af4a552e909e6 Author: Uli Franke Date: Mon Feb 10 05:17:19 2020 +0100 Moved intellisense function to a separate file commit 4f6565c60725b44bdd9cfbffb1d2403bc69f7546 Author: Uli Franke Date: Mon Feb 10 02:33:24 2020 +0100 Minor documentation rub commit 40bb52df5ab3a5fc89cd3933204308817f13e76a Author: Uli Franke Date: Mon Feb 10 02:26:03 2020 +0100 Merge c_cpp_properties results with existing configuration * More unit testing within cocopa. * Implemented c_cpp_properties merging -> compiler analysis results are merged into existing configuration and will preserve configurations of different name than the vscode-studio default configuration name (currently "Arduino"). This opens up the possibility for users to write their own configurations without having to disable the autogeneration. * Implemented "write on change" - `c_cpp_properties.json` will only be written if a new configuration has been detected. commit 67281ae618dfc7036749c8a0b48135d0f29daa68 Author: Uli Franke Date: Sun Feb 9 18:25:01 2020 +0100 Moved arduino specifics from cocopa to vscode-arduino commit 3cba4121b1cf38f7148fd6ae8f36d8b36a73f0ad Author: Uli Franke Date: Sun Feb 9 16:40:00 2020 +0100 Notes about serial monitor * Added more serial monitor ideas from [John Lonergan](https://github.com/microsoft/vscode-arduino/issues/463#issuecomment-583853833) * Added some ideas how to implement a better serial monitor commit d87402d021b997a97b6062a43546baf8a58a64fa Author: Uli Franke Date: Sun Feb 9 13:23:48 2020 +0100 Fix regression and improve regex matching * Fixed regression introduced with adaptions to latest version of cocopa * Made compile command regex match more stringent commit 39c3f798008108282c10c3a82abc7e1569ca3488 Author: Uli Franke Date: Sun Feb 9 11:51:43 2020 +0100 Fix issue 771 * Fixes the line splitting regex as outlined in https://github.com/microsoft/vscode-arduino/pull/771 * Removed a redundand condition commit dd3254dd5b1025a8840c993841720e6b0bb23f68 Author: Uli Franke Date: Sun Feb 9 04:24:52 2020 +0100 Incorporated the latest progress from cocopa development commit bb2ce83e97d82d69c532cc7abbaa8a9a92aaa04d Author: Uli Franke Date: Sat Feb 8 16:29:08 2020 +0100 Try to generate IntelliSense configuration even when the compilation fails commit 819d2f1b470c329d05e7427760778605738f3bce Author: Uli Franke Date: Sat Feb 8 16:12:58 2020 +0100 Added IntelliSense setup auto-generation project (sketch-context) configuration flag which can override the global flag commit f28dd7e8d1a4fe16fda2ffd37465a420f5e090ce Author: Uli Franke Date: Sat Feb 8 13:08:59 2020 +0100 Updated earned :beers: commit 0865c97b571fa63c05d4b950453bb1c64b14728d Author: Uli Franke Date: Sat Feb 8 12:28:25 2020 +0100 Moved compiler parser to cocopa package for better testability and maintainability commit d3372955031ce673c09b2d232bcb9cc51232d8c8 Author: Uli Franke Date: Sat Feb 8 03:10:06 2020 +0100 Documenting ... commit 4a91647ceeb469151f3960607fe616ca12f7629e Author: Uli Franke Date: Fri Feb 7 03:19:09 2020 +0100 Moved TODO in branch documentation commit 59c78cb31382416a24a0b1b950f03d3e1ad5e318 Author: Uli Franke Date: Fri Feb 7 03:15:53 2020 +0100 Added even more TODOs to branch documentation commit ce1b656c50a24362b69c3493817a746dfd97b280 Author: Uli Franke Date: Fri Feb 7 03:11:14 2020 +0100 Added two more TODOs to branch documentation commit 3da2f7600c6bcb9b4b66dcbfb6b82a23e9c9dd7f Author: Uli Franke Date: Fri Feb 7 02:55:26 2020 +0100 IntelliSense on/off configuration and compiler parser injection preparation * Added a global configuration switch which allows the IntelliSense auto-configuration to be turned off * Prepared the compiler parser code to be injected into "upload" and "upload using programmer" without overhead * Updated branch documentation commit bc2b29228ad7dd21682da335436095ca9d90d296 Author: Uli Franke Date: Thu Feb 6 23:34:40 2020 +0100 Documentation updates * Notes regarding settings * Notes where to run the auto-generation commit baaf069352eff3f8502e15ffdc0f7de906a3eb8d Author: Uli Franke Date: Thu Feb 6 23:30:36 2020 +0100 Pre-build command updates * Moved pre-build command into separate member function to reduce code replication, better maintainablility and readability * Added pre-build command to "upload using programmer" since it was (probably unintentional) missing there commit 79bd4762d825682665bc3735f085cba01934fb30 Author: Uli Franke Date: Thu Feb 6 23:29:32 2020 +0100 Improved line splitting of built-in include parser after commenting on a pull request :) commit 16e861dff92570fcaca13690b7962b3e2a46397b Author: Uli Franke Date: Thu Feb 6 21:48:34 2020 +0100 Added IntelliSense compiler parsing engine code * Added IntelliSense compiler parsing engine code * First injection of the compiler command parser and IntelliSense auto-configuration. Currently injected into "verify" only. * Updated branch documentation to reflect the current state of this project commit 82513e4b60899f43b966787aa24ff7dbde17d5ad Author: Uli Franke Date: Thu Feb 6 01:06:03 2020 +0100 More documentation update * More investigations and documentation, especially on intrinsic/built-in compiler header include paths commit 5debfb429d17ff16995440d14fcf544faa13d896 Author: Uli Franke Date: Wed Feb 5 21:33:16 2020 +0100 Update documentation * More documentation on this project * Tried to identify most of the tasks * Added beer money support option commit 0291850c9b31b339e50faad8edbfb344157b5c3e Author: Uli Franke Date: Wed Feb 5 16:28:45 2020 +0100 Branch for the implementation of the automagical IntelliSense configuration commit 48418e20193bdd20c694a287c3873981d7a90df0 Author: Uli Franke Date: Sun Feb 23 20:14:28 2020 +0100 Removed unused import commit 5daa2b1fed43722970328344aa1f7eafbb191015 Author: Håkon Løvdal Date: Fri Dec 11 18:13:55 2020 +0100 Add missing return values commit 57f4aa4caf97c2f28348bc9df9990597e59363f5 Author: Uli Franke Date: Sat Feb 22 14:25:22 2020 +0100 Fix @property commit 2e490b5f4353f202d86f42bfc8e6a395666e7f96 Author: Uli Franke Date: Fri Feb 7 02:08:35 2020 +0100 Fixed spelling. commit ddb804feec82d53e456832543517676893b1ac29 Author: Uli Franke Date: Sat Feb 8 13:05:30 2020 +0100 Fixed misspelled function name commit d6459d0b8cbfbbaabe55f85c18178344b232ed9b Author: Jason Tranchida Date: Tue Dec 8 13:19:45 2020 -0800 Improved handling of programmer selection (#1118) * Improved handling of programmer selection - Selected programmer is now saved to and loaded from the arduino.json file - Arduino.json is monitored for changes, and changing file will update selected programmer & ui - Programmer selection UI now shows both the friendly name of the programmer, as well as the arduino name - Minor fix to deviceContexts to fire change events after all states are modified - Layed groundwork to support querying list of programmers for the current board from arduino toolchain * fix dtr on serial open * fix dtr on serial open * fix linting * pre release v0.3.4 * Add RTS signal on serial open, Add baudrates up to 2000000 (#1142) * add buad rates up to 2M * add rts signal on serial open and buad rate change * add missing space in baud rate array * Quick fix for Intellisense (#1144) * add hardware tool path * intellisense quick fix * add hardware tool path * intellisense quick fix * fix typo * pre release v0.3.4-rc2 * bump to v0.3.4 * Option to use arduino-cli instead of Arduino IDE (#1017) * Hardcoded Arduino-CLI commands for build and upload * Added menu checkbox for Arduino CLI - Upload with programmer is still not supported - Must be created an arduino symlink pointing to arduino-cli * If Arduino-CLI, check for arduino-cli instead of arduino. Not yet supported on Windows or MacOS * Typo * Fixed CI requests * Fixed CI requests * Update src/common/sys/darwin.ts MacOS patch for arduino-cli Co-authored-by: Marc Lage-Vianna * Update src/common/sys/win32.ts Windows patch for arduino-cli Co-authored-by: Marc Lage-Vianna * Trigger * add cli option in commandPath for win32 * add cli support to board and lib managers * rename isArduinoCli to useArduinoCli * adds support for uploading using programmer * simplify getProgrammer * add CLI upload * Update src/arduino/arduino.ts Co-authored-by: Jason Tranchida * refactor uploadUsingProgrammer * fix output path for CLI upload * Update package.json * update cli option text, thanks @maddogjt * update tests Co-authored-by: giuliof Co-authored-by: Marc Lage-Vianna Co-authored-by: Adi Azulay Co-authored-by: Adi Azulay Co-authored-by: Jason Tranchida * Improved handling of programmer selection - Selected programmer is now saved to and loaded from the arduino.json file - Arduino.json is monitored for changes, and changing file will update selected programmer & ui - Programmer selection UI now shows both the friendly name of the programmer, as well as the arduino name - Minor fix to deviceContexts to fire change events after all states are modified - Layed groundwork to support querying list of programmers for the current board from arduino toolchain * add cli suppport for programmers * add documentation Co-authored-by: Marc Goodner Co-authored-by: Adi Azulay Co-authored-by: Giulio Co-authored-by: giuliof Co-authored-by: Marc Lage-Vianna Co-authored-by: Adi Azulay commit ae0ebd43ee4eab1bd8be1043c352197522edb2bf Author: Giulio Date: Tue Dec 8 00:41:05 2020 +0100 Option to use arduino-cli instead of Arduino IDE (#1017) * Hardcoded Arduino-CLI commands for build and upload * Added menu checkbox for Arduino CLI - Upload with programmer is still not supported - Must be created an arduino symlink pointing to arduino-cli * If Arduino-CLI, check for arduino-cli instead of arduino. Not yet supported on Windows or MacOS * Typo * Fixed CI requests * Fixed CI requests * Update src/common/sys/darwin.ts MacOS patch for arduino-cli Co-authored-by: Marc Lage-Vianna * Update src/common/sys/win32.ts Windows patch for arduino-cli Co-authored-by: Marc Lage-Vianna * Trigger * add cli option in commandPath for win32 * add cli support to board and lib managers * rename isArduinoCli to useArduinoCli * adds support for uploading using programmer * simplify getProgrammer * add CLI upload * Update src/arduino/arduino.ts Co-authored-by: Jason Tranchida * refactor uploadUsingProgrammer * fix output path for CLI upload * Update package.json * update cli option text, thanks @maddogjt * update tests Co-authored-by: giuliof Co-authored-by: Marc Lage-Vianna Co-authored-by: Adi Azulay Co-authored-by: Adi Azulay Co-authored-by: Jason Tranchida --- CHANGELOG.md | 18 + README.md | 86 +- ThirdPartyNotices.txt | 29 +- misc/arduinoValidator.json | 34 +- package-lock.json | 141 ++- package.json | 41 +- src/arduino/arduino.ts | 962 +++++++++--------- src/arduino/arduinoContentProvider.ts | 14 +- src/arduino/arduinoSettings.ts | 10 +- src/arduino/board.ts | 94 +- src/arduino/boardManager.ts | 146 ++- src/arduino/intellisense.ts | 330 ++++++ src/arduino/localWebServer.ts | 29 +- src/arduino/package.ts | 88 +- src/arduino/programmer.ts | 67 ++ src/arduino/programmerManager.ts | 137 ++- src/arduino/vscodeSettings.ts | 12 + src/arduinoContext.ts | 6 + src/common/constants.ts | 7 + src/common/platform.ts | 4 +- src/common/sys/darwin.ts | 5 +- src/common/sys/linux.ts | 4 +- src/common/sys/win32.ts | 5 +- src/common/util.ts | 79 +- src/common/workspace.ts | 3 +- src/debug/configurationProvider.ts | 9 +- src/deviceContext.ts | 232 +++-- src/deviceSettings.ts | 276 +++++ src/extension.ts | 119 ++- src/langService/completionProvider.ts | 25 +- src/serialmonitor/serialMonitor.ts | 27 +- src/serialmonitor/usbDetector.ts | 3 + test/boardmanager.test.ts | 30 +- test/commands.test.ts | 15 - test/devicecontext.test.ts | 1 + test/extension.test.ts | 4 +- test/librarymanager.test.ts | 2 +- test/programmermanager.test.ts | 100 ++ test/resources/Arduino15/preferences.txt | 2 +- .../hardware/arduino/avr/programmers.txt | 115 +++ .../hardware/esp8266/esp8266/programmers.txt | 14 + test/resources/blink/.vscode/arduino.json | 3 +- webpack.config.js | 6 +- 43 files changed, 2409 insertions(+), 925 deletions(-) create mode 100644 src/arduino/intellisense.ts create mode 100644 src/arduino/programmer.ts create mode 100644 src/deviceSettings.ts create mode 100644 test/programmermanager.test.ts create mode 100644 test/resources/ArduinoIDE/hardware/arduino/avr/programmers.txt create mode 100644 test/resources/Documents/Arduino/hardware/esp8266/esp8266/programmers.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c9f877d..a0529ebd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,24 @@ # Change Log All notable changes to this project will be documented in this file. +## Version 0.4.0 + +### Added +- Support for Arduino CLI (#1017) + +### Changed +- Autogenerate c_cpp_properties.json with all complier arguments and libraries for IntelliSense (#1183) +- Detects available programmers for selected board (#1118) + +### Fixed +- Typos + +### Breaking Changes +- Unifies all build commands under a single + +### Known Issues +- Arduino CLI doesn't work on Mac (#1205) + ## Version 0.3.5 - Release date: November 22, 2020 diff --git a/README.md b/README.md index 30f60388..3bc3adff 100644 --- a/README.md +++ b/README.md @@ -16,11 +16,19 @@ Welcome to the Visual Studio Code extension for **Arduino** preview ! * Integrated Arduino Debugging New ## Prerequisites -The Arduino IDE is required. Please install it from the [download page](https://www.arduino.cc/en/main/software#download). +Either the Arduino IDE or Arduino CLI are required. + +### Arduino IDE +The Arduino IDE can be installed the Arduino [download page](https://www.arduino.cc/en/main/software#download). - The supported Arduino IDE versions are `1.6.x` and later. - The Windows Store's version of the Arduino IDE is not supported because of the sandbox environment that the application runs in. - *Note:* Arduino IDE `1.8.7` has some breaking changes, causing board package and library installation failures. +### Arduino CLI +The Arduino CLI can be downloaded from the repository's [release page](https://github.com/arduino/arduino-cli/releases/tag/0.13.0) +- The extension has only been tested with v0.13.0. +- If you use the CLI you will have to set `arduino.path` since the CLI does not have a defualt path. + ## Installation Open VS Code and press F1 or Ctrl + Shift + P to open command palette, select **Install Extension** and type `vscode-arduino`. @@ -48,12 +56,16 @@ This extension provides several commands in the Command Palette (F1 o - **Arduino: Select Serial Port**: Change the current serial port. - **Arduino: Send Text to Serial Port**: Send a line of text via the current serial port. - **Arduino: Upload**: Build sketch and upload to Arduino board. +- **Arduino: CLI Upload**: Upload complied code without building sketch (CLI only). - **Arduino: Upload Using Programmer**: Upload using an external programmer. +- **Arduino: CLI Upload Using Programmer**: Upload using an external programmer without building sketch (CLI only). - **Arduino: Verify**: Build sketch. +- **Arduino: Rebuild IntelliSense Configuration**: Forced/manual rebuild of the IntelliSense configuration. The extension analyzes Arduino's build output and sets the Intellisense include paths, defines, compiler arguments accordingly. ## Keybindings - **Arduino: Upload** Alt + Cmd + U *or* Alt + Ctrl + U - **Arduino: Verify** Alt + Cmd + R *or* Alt + Ctrl + R +- **Arduino: Rebuild IntelliSense Configuration** Alt + Cmd + I *or* Alt + Ctrl + I ## Options | Option | Description | @@ -62,11 +74,12 @@ This extension provides several commands in the Command Palette (F1 o | `arduino.commandPath` | Path to an executable (or script) relative to `arduino.path`. The default value is `arduino_debug.exe` for windows,`Contents/MacOS/Arduino` for Mac and `arduino` for Linux, You also can use a custom launch script to run Arduino by modifying this setting. (Requires a restart after change) Example: `run-arduino.bat` for Windows, `Contents/MacOS/run-arduino.sh` for Mac and `bin/run-arduino.sh` for Linux. | | `arduino.additionalUrls` | Additional Boards Manager URLs for 3rd party packages. You can have multiple URLs in one string with a comma(`,`) as separator, or have a string array. The default value is empty. | | `arduino.logLevel` | CLI output log level. Could be info or verbose. The default value is `"info"`. | -| `arduino.allowPDEFiletype` | Allow the VSCode Arduino extension to open .pde files from pre-1.0.0 versions of Ardiuno. Note that this will break Processing code. Default value is `false`. | +| `arduino.allowPDEFiletype` | Allow the VSCode Arduino extension to open .pde files from pre-1.0.0 versions of Ardiuno. Note that this will break Processing code. Default value is `false`. | | `arduino.enableUSBDetection` | Enable/disable USB detection from the VSCode Arduino extension. The default value is `true`. When your device is plugged in to your computer, it will pop up a message "`Detected board ****, Would you like to switch to this board type`". After clicking the `Yes` button, it will automatically detect which serial port (COM) is connected a USB device. If your device does not support this feature, please provide us with the PID/VID of your device; the code format is defined in `misc/usbmapping.json`.To learn more about how to list the vid/pid, use the following tools: https://github.com/EmergingTechnologyAdvisors/node-serialport `npm install -g serialport` `serialport-list -f jsonline`| | `arduino.disableTestingOpen` | Enable/disable automatic sending of a test message to the serial port for checking the open status. The default value is `false` (a test message will be sent). | | `arduino.skipHeaderProvider` | Enable/disable the extension providing completion items for headers. This functionality is included in newer versions of the C++ extension. The default value is `false`.| | `arduino.defaultBaudRate` | Default baud rate for the serial port monitor. The default value is 115200. Supported values are 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 74880, 115200, 230400 and 250000 | +| `arduino.disableIntelliSenseAutoGen` | When `true` vscode-arduino will not auto-generate an IntelliSense configuration (i.e. `.vscode/c_cpp_properties.json`) by analyzing Arduino's compiler output. | The following Visual Studio Code settings are available for the Arduino extension. These can be set in global user preferences Ctrl + , or workspace settings (`.vscode/settings.json`). The latter overrides the former. @@ -75,7 +88,7 @@ The following Visual Studio Code settings are available for the Arduino extensio "arduino.path": "C:/Program Files (x86)/Arduino", "arduino.commandPath": "arduino_debug.exe", "arduino.logLevel": "info", - "arduino.allowPDEFiletype": false, + "arduino.allowPDEFiletype": false, "arduino.enableUSBDetection": true, "arduino.disableTestingOpen": false, "arduino.skipHeaderProvider": false, @@ -98,7 +111,9 @@ The following settings are as per sketch settings of the Arduino extension. You "board": "adafruit:samd:adafruit_feather_m0", "output": "../build", "debugger": "jlink", - "prebuild": "bash prebuild.sh" + "prebuild": "./prebuild.sh", + "postbuild": "./postbuild.sh", + "intelliSenseGen": "global" } ``` - `sketch` - The main sketch file name of Arduino. @@ -106,7 +121,68 @@ The following settings are as per sketch settings of the Arduino extension. You - `board` - Currently selected Arduino board alias. Can be set by the `Arduino: Change Board Type` command. Also, you can find the board list there. - `output` - Arduino build output path. If not set, Arduino will create a new temporary output folder each time, which means it cannot reuse the intermediate result of the previous build leading to long verify/upload time, so it is recommended to set the field. Arduino requires that the output path should not be the workspace itself or in a subfolder of the workspace, otherwise, it may not work correctly. By default, this option is not set. It's worth noting that the contents of this file could be deleted during the build process, so pick (or create) a directory that will not store files you want to keep. - `debugger` - The short name of the debugger that will be used when the board itself does not have a debugger and there is more than one debugger available. You can find the list of debuggers [here](https://github.com/Microsoft/vscode-arduino/blob/master/misc/debuggerUsbMapping.json). By default, this option is not set. -- `prebuild` - External command before building the sketch file. You should only set one `prebuild` command. `command1 && command2` does not work. If you need to run multiple commands before the build, then create a script. +- `prebuild` - External command which will be invoked before any sketch build (verify, upload, ...). For details see the [Pre- and Post-Build Commands](#Pre--and-Post-Build-Commands) section. +- `postbuild` - External command to be run after the sketch has been built successfully. See the afore mentioned section for more details. +- `intelliSenseGen` - Override the global setting for auto-generation of the IntelliSense configuration (i.e. `.vscode/c_cpp_properties.json`). Three options are available: + - `"global"`: Use the global settings (default) + - `"disable"`: Disable the auto-generation even if globally enabled + - `"enable"`: Enable the auto-generation even if globally disabled +- `buildPreferences` - Set Arduino preferences which then are used during any build (verify, upload, ...). This allows for extra defines, compiler options or includes. The preference key-value pairs must be set as follows: +```json + "buildPreferences": [ + ["build.extra_flags", "-DMY_DEFINE=666 -DANOTHER_DEFINE=3.14 -Wall"], + ["compiler.cpp.extra_flags", "-DYET_ANOTER=\"hello\""] + ] +} +``` + +## Pre- and Post-Build Commands +On Windows the commands run within a `cmd`-, on Linux and OSX within a `bash`-instance. Therefore your command can be anything what you can run within those shells. Instead of running a command you can invoke a script. This makes writing more complex pre-/post-build mechanisms much easier and opens up the possibility to run python or other scripting languages. +The commands run within the workspace root directory and vscode-arduino sets the following environment variables: +**`VSCA_BUILD_MODE`** The current build mode, one of `Verifying`, `Uploading`, `Uploading (programmer)` or `Analyzing`. This allows you to run your script on certain build modes only. +**`VSCA_SKETCH`** The sketch file relative to your workspace root directory. +**`VSCA_BOARD`** Your board and configuration, e.g. `arduino:avr:nano:cpu=atmega328`. +**`VSCA_WORKSPACE_DIR`** The absolute path of your workspace root directory. +**`VSCA_LOG_LEVEL`** The current log level. This allows you to control the verbosity of your scripts. +**`VSCA_SERIAL`** The serial port used for uploading. Not set if you haven't set one in your `arduino.json`. +**`VSCA_BUILD_DIR`** The build directory. Not set if you haven't set one in your `arduino.json`. + +For example under Windows the following `arduino.json` setup +```json +{ + "board": "arduino:avr:nano", + "sketch": "test.ino", + "configuration": "cpu=atmega328", + "prebuild": "IF \"%VSCA_BUILD_MODE%\"==\"Verifying\" (echo VSCA_BUILD_MODE=%VSCA_BUILD_MODE% && echo VSCA_BOARD=%VSCA_BOARD%)" +} +``` +will produce +``` +[Starting] Verifying sketch 'test.ino' +Running pre-build command: "IF "%VSCA_BUILD_MODE%"=="Verifying" (echo VSCA_BUILD_MODE=%VSCA_BUILD_MODE% && echo VSCA_BOARD=%VSCA_BOARD%)" +VSCA_BUILD_MODE=Verifying +VSCA_BOARD=arduino:avr:nano:cpu=atmega328 +Loading configuration... +<...> +``` +when verifying. + +## IntelliSense +vscode-arduino auto-configures IntelliSense by default. vscode-arduino analyzes Arduino's compiler output by running a separate build and generates the corresponding configuration file at `.vscode/c_cpp_properties.json`. vscode-arduino tries as hard as possible to keep things up to date, e.g. it runs the analysis when switching the board or the sketch. + +It doesn't makes sense though to run the analysis repeatedly. Therefore if the workspace reports problems ("squiggles") - for instance after adding new includes from a new library - run the analysis manually: + +Manual rebuild: **Arduino: Rebuild IntelliSense Configuration**, +Keybindings: Alt + Cmd + I *or* Alt + Ctrl + I + +When the analysis is invoked manually it ignores any global and project specific disable. + +### IntelliSense Configurations +vscode-arduino's analysis stores the result as a dedicated IntelliSense-configuration named `Arduino`. You have to select it from the far right of the status bar when you're in one of your source files as shown here: + +![74001156-cfce8280-496a-11ea-9b9d-7d30c83765c1](https://user-images.githubusercontent.com/21954933/74351237-2696ea80-4db7-11ea-9f7a-1bfc652ad5f5.png) + +This system allows you to setup and use own IntelliSense configurations in parallel to the automatically generated configurations provided through vscode-arduino. Just add your configuration to `c_cpp_properties.json` and name it differently from the default configuration (`Arduino`), e.g. `My awesome configuration` and select it from the status bar or via the command palette command **C/C++: Select a Configuration...** ## Debugging Arduino Code preview Before you start to debug your Arduino code, please read [this document](https://code.visualstudio.com/docs/editor/debugging) to learn about the basic mechanisms of debugging in Visual Studio Code. Also see [debugging for C++ in VSCode](https://code.visualstudio.com/docs/languages/cpp#_debugging) for further reference. diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index fdacfadc..95505d66 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -25,7 +25,7 @@ Visual Studio Code Extension for Arduino incorporates third party material from 18. vscode-extension-telemetry (https://github.com/Microsoft/vscode-extension-telemetry) 19. winreg (https://github.com/fresc81/node-winreg) 20. Winston (https://github.com/winstonjs/winston) - +21. cocopa (https://github.com/elektronikworkshop/cocopa) %% body-parser NOTICES, INFORMATION, AND LICENSE BEGIN HERE ========================================= @@ -532,4 +532,31 @@ THE SOFTWARE. ========================================= END OF Winston NOTICES, INFORMATION, AND LICENSE +%% cocopa NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= +Copyright (C) 2020 Uli Franke - Elektronik Workshop + +All rights reserved. + +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +========================================= +END OF cocopa NOTICES, INFORMATION, AND LICENSE diff --git a/misc/arduinoValidator.json b/misc/arduinoValidator.json index 73baff4f..5386fc4f 100644 --- a/misc/arduinoValidator.json +++ b/misc/arduinoValidator.json @@ -32,6 +32,38 @@ "description": "Arduino Debugger Settings", "type": "string", "minLength": 1 + }, + "intelliSenseGen": { + "description": "Disable/enable the automatic generation of the IntelliSense configuration file (c_cpp_properties.json) for this project (overrides the global setting). When set to \"global\" the global extension settings will be used.", + "type": "string", + "default": "global", + "enum": [ + "global", + "disable", + "enable" + ] + }, + "prebuild": { + "description": "Command to be run before every build", + "type": "string", + "minLength": 1 + }, + "postbuild": { + "description": "Command to be run after every build", + "type": "string", + "minLength": 1 + }, + "buildPreferences": { + "description": "Arduino preferences which are passed to the Arduino back-end during build", + "type": "array", + "items": { + "type":"array", + "minItems": 2, + "maxItems": 2, + "items": { + "type": "string" + } + } } } -} \ No newline at end of file +} diff --git a/package-lock.json b/package-lock.json index 8229e3f9..50043aaa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "vscode-arduino", - "version": "0.3.5", + "version": "0.4.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -219,8 +219,7 @@ "@types/color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", - "dev": true + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" }, "@types/compare-versions": { "version": "3.3.0", @@ -485,15 +484,15 @@ } }, "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "dev": true, "requires": { - "fast-deep-equal": "^3.1.1", + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "json-schema-traverse": "^0.3.0" } }, "ajv-errors": { @@ -546,7 +545,6 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, "requires": { "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" @@ -556,7 +554,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "requires": { "color-name": "~1.1.4" } @@ -564,8 +561,7 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" } } }, @@ -1561,6 +1557,38 @@ "semver": "^5.4.1" } }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "cocopa": { + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/cocopa/-/cocopa-0.0.13.tgz", + "integrity": "sha512-MKWdCbaC9MpT+CMNXRP2rufpIndIaCKY1KD3XXwg6I2jNI1uFjEKNGXObL1mJ+7X53FTzKaZydJbPinCG+WJTQ==", + "requires": { + "chalk": "^3.0.0", + "commander": "^4.1.1", + "shlex": "^2.0.1" + }, + "dependencies": { + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==" + } + } + }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -2429,6 +2457,18 @@ "v8-compile-cache": "^2.0.3" }, "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", @@ -2444,6 +2484,12 @@ "ms": "^2.1.1" } }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, "glob-parent": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", @@ -2459,6 +2505,12 @@ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -2944,9 +2996,9 @@ } }, "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, "fast-json-stable-stringify": { @@ -3507,12 +3559,6 @@ "dev": true, "optional": true }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, @@ -5046,9 +5092,9 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "inquirer": { "version": "7.3.3", @@ -5472,9 +5518,9 @@ "dev": true }, "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", "dev": true }, "json-stable-stringify-without-jsonify": { @@ -7648,6 +7694,11 @@ "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" }, + "shlex": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/shlex/-/shlex-2.0.2.tgz", + "integrity": "sha512-i4p9nNXgBTILspHwZlBCNsZzwuVWW8SFx5dyIONrjL0R+AbMOPbg7ndqgGfjYivkYRTtZMKqIT8HT+QyOhPQWA==" + }, "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", @@ -8101,7 +8152,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, "requires": { "has-flag": "^4.0.0" }, @@ -8109,8 +8159,7 @@ "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" } } }, @@ -8136,6 +8185,18 @@ "string-width": "^3.0.0" }, "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", @@ -8148,12 +8209,24 @@ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -8544,9 +8617,9 @@ } }, "typescript": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", - "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", + "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", "dev": true }, "unc-path-regex": { diff --git a/package.json b/package.json index 6629987b..a97d952f 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vscode-arduino", "displayName": "Arduino", "description": "Arduino for Visual Studio Code", - "version": "0.3.5", + "version": "0.4.0", "publisher": "vsciot-vscode", "aiKey": "83dd2c27-6594-41d3-85a9-bdb22070eb42", "preview": true, @@ -36,11 +36,13 @@ "*", "onCommand:arduino.verify", "onCommand:arduino.upload", + "onCommand:arduino.cliUpload", "onCommand:arduino.uploadUsingProgrammer", + "onCommand:arduiono.cliUploadUsingProgrammer", + "onCommand:arduino.rebuildIntelliSenseConfig", "onCommand:arduino.selectProgrammer", "onCommand:arduino.selectSerialPort", "onCommand:arduino.changeBaudRate", - "onCommand:arduino.addLibPath", "onCommand:arduino.openSerialMonitor", "onCommand:arduino.sendMessageToSerialPort", "onCommand:arduino.closeSerialMonitor", @@ -93,10 +95,22 @@ "light": "images/ArduinoUpload_16.svg" } }, + { + "command": "arduino.cliUpload", + "title": "Arduino CLI: Upload" + }, { "command": "arduino.uploadUsingProgrammer", "title": "Arduino: Upload Using Programmer" }, + { + "command": "arduino.cliUploadUsingProgrammer", + "title": "Arduino CLI: Upload Using Programmer" + }, + { + "command": "arduino.rebuildIntelliSenseConfig", + "title": "Arduino: Rebuild IntelliSense Configuration" + }, { "command": "arduino.selectProgrammer", "title": "Arduino: Select Programmer" @@ -235,7 +249,7 @@ }, "targetArchitecture": { "type": "string", - "description": "The architecture of the debuggee.", + "description": "The architecture of the debugger.", "default": "arm" }, "cwd": { @@ -436,12 +450,22 @@ "command": "arduino.upload", "key": "ctrl+alt+u", "mac": "cmd+alt+u" + }, + { + "command": "arduino.rebuildIntelliSenseConfig", + "key": "ctrl+alt+i", + "mac": "cmd+alt+i" } ], "configuration": { "type": "object", "title": "Arduino configuration", "properties": { + "arduino.useArduinoCli": { + "type": "boolean", + "default": false, + "markdownDescription": "Use Arduino CLI installed instead of Arduino IDE. `#arduino.path#` must be set, as there is no default path for 'arduino-cli'. (Requires a restart after change)" + }, "arduino.path": { "type": "string", "default": "", @@ -491,6 +515,11 @@ "arduino.defaultBaudRate": { "type": "number", "default": 115200 + }, + "arduino.disableIntelliSenseAutoGen": { + "type": "boolean", + "default": false, + "description": "When disabled vscode-arduino will not auto-generate an IntelliSense configuration (i.e. c_cpp_properties.json) by analyzing the compiler output." } } }, @@ -546,10 +575,11 @@ "devDependencies": { "@types/compare-versions": "^3.0.0", "@types/mocha": "^5.2.7", - "@types/node": "^6.0.40", + "@types/node": "^6.14.9", "@types/vscode": "^1.43.0", "@types/winreg": "^1.2.30", "acorn": "^7.4.0", + "ajv": "^5.0.0", "del": "^2.2.2", "eslint": "^6.8.0", "eslint-config-standard": "^10.2.1", @@ -570,12 +600,13 @@ "plugin-error": "^1.0.1", "tslint": "^5.20.1", "typemoq": "^1.6.0", - "typescript": "^2.2.1", + "typescript": "^3.7.5", "vscode-test": "^1.4.0", "webpack": "^4.44.1" }, "dependencies": { "body-parser": "^1.16.1", + "cocopa": "0.0.13", "compare-versions": "^3.4.0", "eventemitter2": "^4.1.0", "express": "^4.14.1", diff --git a/src/arduino/arduino.ts b/src/arduino/arduino.ts index 263a5069..785df236 100644 --- a/src/arduino/arduino.ts +++ b/src/arduino/arduino.ts @@ -9,12 +9,15 @@ import * as vscode from "vscode"; import * as constants from "../common/constants"; import * as util from "../common/util"; -import * as Logger from "../logger/logger"; +import * as logger from "../logger/logger"; import { DeviceContext } from "../deviceContext"; import { IArduinoSettings } from "./arduinoSettings"; import { BoardManager } from "./boardManager"; import { ExampleManager } from "./exampleManager"; +import { AnalysisManager, + isCompilerParserEnabled, + makeCompilerParserContext } from "./intellisense"; import { LibraryManager } from "./libraryManager"; import { VscodeSettings } from "./vscodeSettings"; @@ -24,6 +27,20 @@ import { SerialMonitor } from "../serialmonitor/serialMonitor"; import { UsbDetector } from "../serialmonitor/usbDetector"; import { ProgrammerManager } from "./programmerManager"; +/** + * Supported build modes. For further explanation see the documentation + * of ArduinoApp.build(). + * The strings are used for status reporting within the above function. + */ +export enum BuildMode { + Verify = "Verifying", + Analyze = "Analyzing", + Upload = "Uploading", + CliUpload = "Uploading using Arduino CLI", + UploadProgrammer = "Uploading (programmer)", + CliUploadProgrammer = "Uploading (programmer) using Arduino CLI", +}; + /** * Represent an Arduino application based on the official Arduino IDE. */ @@ -37,10 +54,30 @@ export class ArduinoApp { private _programmerManager: ProgrammerManager; + /** + * IntelliSense analysis manager. + * Makes sure that analysis builds and regular builds go along + * and that multiple subsequent analysis requests - as triggered + * by board/board-configuration changes - are bundled to a single + * analysis build run. + */ + private _analysisManager: AnalysisManager; + + /** + * Indicates if a build is currently in progress. + * If so any call to this.build() will return false immediately. + */ + private _building: boolean = false; + /** * @param {IArduinoSettings} _settings ArduinoSetting object. */ constructor(private _settings: IArduinoSettings) { + const analysisDelayMs = 1000 * 3; + this._analysisManager = new AnalysisManager( + () => this._building, + async () => { await this.build(BuildMode.Analyze); }, + analysisDelayMs); } /** @@ -63,6 +100,17 @@ export class ArduinoApp { } catch (ex) { } } + + // set up event handling for IntelliSense analysis + const requestAnalysis = async () => { + if (isCompilerParserEnabled()) { + await this._analysisManager.requestAnalysis(); + } + }; + const dc = DeviceContext.getInstance(); + dc.onChangeBoard(requestAnalysis); + dc.onChangeConfiguration(requestAnalysis); + dc.onChangeSketch(requestAnalysis); } /** @@ -87,381 +135,59 @@ export class ArduinoApp { public async setPref(key, value) { try { await util.spawn(this._settings.commandPath, - null, - ["--pref", `${key}=${value}`, "--save-prefs"]); + ["--pref", `${key}=${value}`, "--save-prefs"]); } catch (ex) { } } - public async upload() { - const dc = DeviceContext.getInstance(); - const boardDescriptor = this.getBoardBuildString(); - if (!boardDescriptor) { - return; - } - - if (!ArduinoWorkspace.rootPath) { - vscode.window.showWarningMessage("Cannot find the sketch file."); - return; - } - - if (!dc.sketch || !util.fileExistsSync(path.join(ArduinoWorkspace.rootPath, dc.sketch))) { - await this.getMainSketch(dc); - } - - if ((!dc.configuration || !/upload_method=[^=,]*st[^,]*link/i.test(dc.configuration)) && !dc.port) { - const choice = await vscode.window.showInformationMessage( - "Serial port is not specified. Do you want to select a serial port for uploading?", - "Yes", "No"); - if (choice === "Yes") { - vscode.commands.executeCommand("arduino.selectSerialPort"); - } - return; - } - - arduinoChannel.show(); - arduinoChannel.start(`Upload sketch - ${dc.sketch}`); - - const serialMonitor = SerialMonitor.getInstance(); - - const needRestore = await serialMonitor.closeSerialMonitor(dc.port); - UsbDetector.getInstance().pauseListening(); - await vscode.workspace.saveAll(false); - - if (dc.prebuild) { - arduinoChannel.info(`Run prebuild command: ${dc.prebuild}`); - const prebuildargs = dc.prebuild.split(" "); - const prebuildCommand = prebuildargs.shift(); - try { - await util.spawn(prebuildCommand, arduinoChannel.channel, prebuildargs, { shell: true, cwd: ArduinoWorkspace.rootPath }); - } catch (ex) { - arduinoChannel.error(`Run prebuild failed: \n${ex.error}`); - return; - } - } - - const appPath = path.join(ArduinoWorkspace.rootPath, dc.sketch); - const args = ["--upload", "--board", boardDescriptor]; - if (dc.port) { - args.push("--port", dc.port); - } - args.push(appPath); - if (VscodeSettings.getInstance().logLevel === "verbose") { - args.push("--verbose"); - } - if (dc.output) { - const outputPath = path.resolve(ArduinoWorkspace.rootPath, dc.output); - const dirPath = path.dirname(outputPath); - if (!util.directoryExistsSync(dirPath)) { - Logger.notifyUserError("InvalidOutPutPath", new Error(constants.messages.INVALID_OUTPUT_PATH + outputPath)); - return; - } - - args.push("--pref", `build.path=${outputPath}`); - arduinoChannel.info(`Please see the build logs in Output path: ${outputPath}`); - } else { - const msg = "Output path is not specified. Unable to reuse previously compiled files. Upload could be slow. See README."; - arduinoChannel.warning(msg); - } - await util.spawn(this._settings.commandPath, arduinoChannel.channel, args).then(async () => { - UsbDetector.getInstance().resumeListening(); - if (needRestore) { - await serialMonitor.openSerialMonitor(); - } - arduinoChannel.end(`Uploaded the sketch: ${dc.sketch}${os.EOL}`); - }, (reason) => { - arduinoChannel.error(`Exit with code=${reason.code}${os.EOL}`); - }); - } - - public async uploadUsingProgrammer() { - const dc = DeviceContext.getInstance(); - const boardDescriptor = this.getBoardBuildString(); - if (!boardDescriptor) { - return; - } - - const selectProgrammer = this.getProgrammerString(); - if (!selectProgrammer) { - return; - } - - if (!ArduinoWorkspace.rootPath) { - vscode.window.showWarningMessage("Cannot find the sketch file."); - return; - } - - if (!dc.sketch || !util.fileExistsSync(path.join(ArduinoWorkspace.rootPath, dc.sketch))) { - await this.getMainSketch(dc); - } - if (!dc.port) { - const choice = await vscode.window.showInformationMessage( - "Serial port is not specified. Do you want to select a serial port for uploading?", - "Yes", "No"); - if (choice === "Yes") { - vscode.commands.executeCommand("arduino.selectSerialPort"); - } - return; - } - - arduinoChannel.show(); - arduinoChannel.start(`Upload sketch - ${dc.sketch}`); - - const serialMonitor = SerialMonitor.getInstance(); - - const needRestore = await serialMonitor.closeSerialMonitor(dc.port); - UsbDetector.getInstance().pauseListening(); - await vscode.workspace.saveAll(false); - - const appPath = path.join(ArduinoWorkspace.rootPath, dc.sketch); - const args = ["--upload", "--board", boardDescriptor, "--port", dc.port, "--useprogrammer", - "--pref", "programmer=" + selectProgrammer, appPath]; - if (VscodeSettings.getInstance().logLevel === "verbose") { - args.push("--verbose"); - } - if (dc.output) { - const outputPath = path.resolve(ArduinoWorkspace.rootPath, dc.output); - const dirPath = path.dirname(outputPath); - if (!util.directoryExistsSync(dirPath)) { - Logger.notifyUserError("InvalidOutPutPath", new Error(constants.messages.INVALID_OUTPUT_PATH + outputPath)); - return; - } - - args.push("--pref", `build.path=${outputPath}`); - arduinoChannel.info(`Please see the build logs in Output path: ${outputPath}`); - } else { - const msg = "Output path is not specified. Unable to reuse previously compiled files. Upload could be slow. See README."; - arduinoChannel.warning(msg); - } - await util.spawn(this._settings.commandPath, arduinoChannel.channel, args).then(async () => { - UsbDetector.getInstance().resumeListening(); - if (needRestore) { - await serialMonitor.openSerialMonitor(); - } - arduinoChannel.end(`Uploaded the sketch: ${dc.sketch}${os.EOL}`); - }, (reason) => { - arduinoChannel.error(`Exit with code=${reason.code}${os.EOL}`); - }); + /** + * Returns true if a build is currently in progress. + */ + public get building() { + return this._building; } - public async verify(output: string = "") { - const dc = DeviceContext.getInstance(); - const boardDescriptor = this.getBoardBuildString(); - if (!boardDescriptor) { - return; - } - - if (!ArduinoWorkspace.rootPath) { - vscode.window.showWarningMessage("Cannot find the sketch file."); - return; - } - - if (!dc.sketch || !util.fileExistsSync(path.join(ArduinoWorkspace.rootPath, dc.sketch))) { - await this.getMainSketch(dc); - } - - await vscode.workspace.saveAll(false); - - arduinoChannel.start(`Verify sketch - ${dc.sketch}`); - - if (dc.prebuild) { - arduinoChannel.info(`Run prebuild command: ${dc.prebuild}`); - const prebuildargs = dc.prebuild.split(" "); - const prebuildCommand = prebuildargs.shift(); - try { - await util.spawn(prebuildCommand, arduinoChannel.channel, prebuildargs, { shell: true, cwd: ArduinoWorkspace.rootPath }); - } catch (ex) { - arduinoChannel.error(`Run prebuild failed: \n${ex.error}`); - return; - } - } - - const appPath = path.join(ArduinoWorkspace.rootPath, dc.sketch); - const args = ["--verify", "--board", boardDescriptor, appPath]; - if (VscodeSettings.getInstance().logLevel === "verbose") { - args.push("--verbose"); - } - if (output || dc.output) { - const outputPath = path.resolve(ArduinoWorkspace.rootPath, output || dc.output); - const dirPath = path.dirname(outputPath); - if (!util.directoryExistsSync(dirPath)) { - Logger.notifyUserError("InvalidOutPutPath", new Error(constants.messages.INVALID_OUTPUT_PATH + outputPath)); - return; - } - - args.push("--pref", `build.path=${outputPath}`); - arduinoChannel.info(`Please see the build logs in Output path: ${outputPath}`); - } else { - const msg = "Output path is not specified. Unable to reuse previously compiled files. Verify could be slow. See README."; - arduinoChannel.warning(msg); - } + /** + * Runs the arduino builder to build/compile and - if necessary - upload + * the current sketch. + * @param buildMode Build mode. + * * BuildMode.Upload: Compile and upload + * * BuildMode.UploadProgrammer: Compile and upload using the user + * selectable programmer + * * BuildMode.Analyze: Compile, analyze the output and generate + * IntelliSense configuration from it. + * * BuildMode.Verify: Just compile. + * All build modes except for BuildMode.Analyze run interactively, i.e. if + * something is missing, it tries to query the user for the missing piece + * of information (sketch, board, etc.). Analyze runs non interactively and + * just returns false. + * @param buildDir Override the build directory set by the project settings + * with the given directory. + * @returns true on success, false if + * * another build is currently in progress + * * board- or programmer-manager aren't initialized yet + * * or something went wrong during the build + */ + public async build(buildMode: BuildMode, buildDir?: string) { - arduinoChannel.show(); - // we need to return the result of verify - try { - await util.spawn(this._settings.commandPath, arduinoChannel.channel, args); - arduinoChannel.end(`Finished verify sketch - ${dc.sketch}${os.EOL}`); - return true; - } catch (reason) { - const msg = reason.code ? - `Exit with code=${reason.code}${os.EOL}` : - reason.message ? - reason.message : - JSON.stringify(reason); - arduinoChannel.error(msg); + if (!this._boardManager || !this._programmerManager || this._building) { return false; } - } - - public tryToUpdateIncludePaths() { - const configFilePath = path.join(ArduinoWorkspace.rootPath, constants.CPP_CONFIG_FILE); - if (!fs.existsSync(configFilePath)) { - return; - } - const cppConfigFile = fs.readFileSync(configFilePath, "utf8"); - const cppConfig = JSON.parse(cppConfigFile) as { configurations: Array<{ - includePath: string[], - forcedInclude: string[], - defines: string[], - }> }; - const libPaths = this.getDefaultPackageLibPaths(); - const defaultForcedInclude = this.getDefaultForcedIncludeFiles(); - const defines = this.getDefaultDefines(); - const configuration = cppConfig.configurations[0]; - - let cppConfigFileUpdated = false; - // cpp extension changes \\ to \\\\ in paths in JSON string, revert them first - configuration.includePath = configuration.includePath.map((path) => path.replace(/\\\\/g, "\\")); - configuration.forcedInclude = configuration.forcedInclude.map((path) => path.replace(/\\\\/g, "\\")); - configuration.defines = configuration.defines.map((path) => path.replace(/\\\\/g, "\\")); - - for (const libPath of libPaths) { - if (configuration.includePath.indexOf(libPath) === -1) { - cppConfigFileUpdated = true; - configuration.includePath.push(libPath); - } - } - for (const forcedIncludePath of defaultForcedInclude) { - if (configuration.forcedInclude.indexOf(forcedIncludePath) === -1) { - cppConfigFileUpdated = true; - configuration.forcedInclude.push(forcedIncludePath); - } - } - - for (const define of defines) { - if (configuration.defines.indexOf(define) === -1) { - cppConfigFileUpdated = true; - configuration.defines.push(define); - } - } - // remove all unexisting paths - // concern mistake removal, comment temporary - // for (let pathIndex = 0; pathIndex < configuration.includePath.length; pathIndex++) { - // let libPath = configuration.includePath[pathIndex]; - // if (libPath.indexOf("${workspaceFolder}") !== -1) { - // continue; - // } - // if (/\*$/.test(libPath)) { - // libPath = libPath.match(/^[^\*]*/)[0]; - // } - // if (!fs.existsSync(libPath)) { - // cppConfigFileUpdated = true; - // configuration.includePath.splice(pathIndex, 1); - // pathIndex--; - // } - // } - // for (let pathIndex = 0; pathIndex < configuration.forcedInclude.length; pathIndex++) { - // const forcedIncludePath = configuration.forcedInclude[pathIndex]; - // if (forcedIncludePath.indexOf("${workspaceFolder}") !== -1) { - // continue; - // } - // if (!fs.existsSync(forcedIncludePath)) { - // cppConfigFileUpdated = true; - // configuration.forcedInclude.splice(pathIndex, 1); - // pathIndex--; - // } - // } - - if (cppConfigFileUpdated) { - fs.writeFileSync(configFilePath, JSON.stringify(cppConfig, null, 4)); - } - } - - // Add selected library path to the intellisense search path. - public addLibPath(libraryPath: string) { - let libPaths; - if (libraryPath) { - libPaths = [libraryPath]; - } else { - libPaths = this.getDefaultPackageLibPaths(); - } - - const defaultForcedInclude = this.getDefaultForcedIncludeFiles(); - const defaultDefines = this.getDefaultDefines(); + this._building = true; - if (!ArduinoWorkspace.rootPath) { - return; - } - const configFilePath = path.join(ArduinoWorkspace.rootPath, constants.CPP_CONFIG_FILE); - let deviceContext = null; - if (!util.fileExistsSync(configFilePath)) { - util.mkdirRecursivelySync(path.dirname(configFilePath)); - deviceContext = {}; - } else { - deviceContext = util.tryParseJSON(fs.readFileSync(configFilePath, "utf8")); - } - if (!deviceContext) { - Logger.notifyAndThrowUserError("arduinoFileError", new Error(constants.messages.ARDUINO_FILE_ERROR)); - } - - deviceContext.configurations = deviceContext.configurations || []; - let configSection = null; - deviceContext.configurations.forEach((section) => { - if (section.name === util.getCppConfigPlatform()) { - configSection = section; - } - }); - - if (!configSection) { - configSection = { - name: util.getCppConfigPlatform(), - includePath: [], - }; - deviceContext.configurations.push(configSection); - } - - libPaths.forEach((childLibPath) => { - childLibPath = path.resolve(path.normalize(childLibPath)); - if (configSection.includePath && configSection.includePath.length) { - for (const existingPath of configSection.includePath) { - if (childLibPath === path.resolve(path.normalize(existingPath))) { - return; - } - } - } else { - configSection.includePath = []; - } - configSection.includePath.unshift(childLibPath); + return await this._build(buildMode, buildDir) + .then((ret) => { + this._building = false; + return ret; + }) + .catch((reason) => { + this._building = false; + logger.notifyUserError("ArduinoApp.build", + reason, + `Unhandled exception when cleaning up build "${buildMode}": ${JSON.stringify(reason)}`); + return false; }); - - if (!configSection.forcedInclude) { - configSection.forcedInclude = defaultForcedInclude; - } else { - for (let i = 0; i < configSection.forcedInclude.length; i++) { - if (/arduino\.h$/i.test(configSection.forcedInclude[i])) { - configSection.forcedInclude.splice(i, 1); - i--; - } - } - configSection.forcedInclude = defaultForcedInclude.concat(configSection.forcedInclude); - } - - if (!configSection.defines) { - configSection.defines = defaultDefines; - } - - fs.writeFileSync(configFilePath, JSON.stringify(deviceContext, null, 4)); } // Include the *.h header files from selected library to the arduino sketch. @@ -495,9 +221,14 @@ export class ArduinoApp { } } - /** - * Install arduino board package based on package name and platform hardware architecture. - */ + /** + * Installs arduino board package. + * (If using the aduino CLI this installs the corrosponding core.) + * @param {string} packageName - board vendor + * @param {string} arch - board architecture + * @param {string} version - version of board package or core to download + * @param {boolean} [showOutput=true] - show raw output from command + */ public async installBoard(packageName: string, arch: string = "", version: string = "", showOutput: boolean = true) { arduinoChannel.show(); const updatingIndex = packageName === "dummy" && !arch && !version; @@ -505,24 +236,32 @@ export class ArduinoApp { arduinoChannel.start(`Update package index files...`); } else { try { - const packagePath = path.join(this._settings.packagePath, "packages", packageName); + const packagePath = path.join(this._settings.packagePath, "packages", packageName, arch); if (util.directoryExistsSync(packagePath)) { util.rmdirRecursivelySync(packagePath); } arduinoChannel.start(`Install package - ${packageName}...`); } catch (error) { arduinoChannel.start(`Install package - ${packageName} failed under directory : ${error.path}${os.EOL} -Please make sure the folder is not occupied by other procedures .`); + Please make sure the folder is not occupied by other procedures .`); arduinoChannel.error(`Error message - ${error.message}${os.EOL}`); arduinoChannel.error(`Exit with code=${error.code}${os.EOL}`); return; } } + arduinoChannel.info(`${packageName}${arch && ":" + arch}${version && ":" + version}`); try { - await util.spawn(this._settings.commandPath, - showOutput ? arduinoChannel.channel : null, - ["--install-boards", `${packageName}${arch && ":" + arch}${version && ":" + version}`]); - + if (this.useArduinoCli()) { + await util.spawn(this._settings.commandPath, + ["core", "install", `${packageName}${arch && ":" + arch}${version && "@" + version}`], + undefined, + { channel: showOutput ? arduinoChannel.channel : null }); + } else { + await util.spawn(this._settings.commandPath, + ["--install-boards", `${packageName}${arch && ":" + arch}${version && ":" + version}`], + undefined, + { channel: showOutput ? arduinoChannel.channel : null }); + } if (updatingIndex) { arduinoChannel.end("Updated package index files."); } else { @@ -548,6 +287,13 @@ Please make sure the folder is not occupied by other procedures .`); arduinoChannel.end(`Uninstalled board package - ${boardName}${os.EOL}`); } + /** + * Downloads or updates a library + * @param {string} libName - name of the library to download + * @param {string} version - version of library to download + * @param {boolean} [showOutput=true] - show raw output from command + */ + public async installLibrary(libName: string, version: string = "", showOutput: boolean = true) { arduinoChannel.show(); const updatingIndex = (libName === "dummy" && !version); @@ -557,10 +303,17 @@ Please make sure the folder is not occupied by other procedures .`); arduinoChannel.start(`Install library - ${libName}`); } try { - await util.spawn(this._settings.commandPath, - showOutput ? arduinoChannel.channel : null, - ["--install-library", `${libName}${version && ":" + version}`]); - + if (this.useArduinoCli()) { + await util.spawn(this._settings.commandPath, + ["lib", "install", `${libName}${version && "@" + version}`], + undefined, + { channel: showOutput ? arduinoChannel.channel : undefined }); + } else { + await util.spawn(this._settings.commandPath, + ["--install-library", `${libName}${version && ":" + version}`], + undefined, + { channel: showOutput ? arduinoChannel.channel : undefined }); + } if (updatingIndex) { arduinoChannel.end("Updated library index files."); } else { @@ -586,62 +339,6 @@ Please make sure the folder is not occupied by other procedures .`); arduinoChannel.end(`Removed library - ${libName}${os.EOL}`); } - public getDefaultPackageLibPaths(): string[] { - const result = []; - const boardDescriptor = this._boardManager.currentBoard; - if (!boardDescriptor) { - return result; - } - const toolsPath = boardDescriptor.platform.rootBoardPath; - result.push(path.normalize(path.join(toolsPath, "**"))); - const hardwareToolPath = path.join(toolsPath, "..", "..", "tools"); - if (fs.existsSync(hardwareToolPath)) { - result.push(path.normalize(path.join(hardwareToolPath, "**"))); - } - - // Add default libraries to include path - result.push(path.normalize(path.join(this._settings.defaultLibPath, "**"))); - - const userLibsPath = (path.join(this._settings.sketchbookPath, "libraries", "**")); - result.push(userLibsPath); - // if (util.directoryExistsSync(path.join(toolsPath, "cores"))) { - // const coreLibs = fs.readdirSync(path.join(toolsPath, "cores")); - // if (coreLibs && coreLibs.length > 0) { - // coreLibs.forEach((coreLib) => { - // result.push(path.normalize(path.join(toolsPath, "cores", coreLib))); - // }); - // } - // } - // return result; - - // /hardware// -> /tools - const toolPath = path.join(toolsPath, "..", "..", "..", "tools"); - if (fs.existsSync(toolPath)) { - result.push(path.normalize(path.join(toolPath, "**"))); - } - return result; - } - - public getDefaultForcedIncludeFiles(): string[] { - const result = []; - const boardDescriptor = this._boardManager.currentBoard; - if (!boardDescriptor) { - return result; - } - const arduinoHeadFilePath = path.normalize(path.join(boardDescriptor.platform.rootBoardPath, "cores", "arduino", "Arduino.h")); - if (fs.existsSync(arduinoHeadFilePath)) { - result.push(arduinoHeadFilePath); - } - return result; - } - - public getDefaultDefines(): string[] { - const result = []; - // USBCON is required in order for Serial to be recognized by intellisense - result.push("USBCON"); - return result; - } - public openExample(example) { function tmpName(name) { let counter = 0; @@ -681,6 +378,7 @@ Please make sure the folder is not occupied by other procedures .`); const dc = DeviceContext.getInstance(); const arduinoJson = { sketch: sketchFile, + // TODO EW, 2020-02-18: COM1 is Windows specific - what about OSX and Linux users? port: dc.port || "COM1", board: dc.board, configuration: dc.configuration, @@ -688,43 +386,6 @@ Please make sure the folder is not occupied by other procedures .`); const arduinoConfigFilePath = path.join(destExample, constants.ARDUINO_CONFIG_FILE); util.mkdirRecursivelySync(path.dirname(arduinoConfigFilePath)); fs.writeFileSync(arduinoConfigFilePath, JSON.stringify(arduinoJson, null, 4)); - - // Generate cpptools intellisense config - const cppConfigFilePath = path.join(destExample, constants.CPP_CONFIG_FILE); - - // Current workspace - let includePath = ["${workspaceRoot}"]; - // Defaut package for this board - const defaultPackageLibPaths = this.getDefaultPackageLibPaths(); - includePath = includePath.concat(defaultPackageLibPaths); - // Arduino built-in package tools - includePath.push(path.join(this._settings.arduinoPath, "hardware", "tools", "**")); - // Arduino built-in libraries - includePath.push(path.join(this._settings.arduinoPath, "libraries", "**")); - // Arduino custom package tools - includePath.push(path.join(this._settings.sketchbookPath, "hardware", "tools", "**")); - // Arduino custom libraries - includePath.push(path.join(this._settings.sketchbookPath, "libraries", "**")); - - const forcedInclude = this.getDefaultForcedIncludeFiles(); - - const defines = [ - "ARDUINO=10800", - ]; - const cppConfig = { - configurations: [{ - name: util.getCppConfigPlatform(), - defines, - includePath, - forcedInclude, - intelliSenseMode: "clang-x64", - cStandard: "c11", - cppStandard: "c++17", - }], - version: 3, - }; - util.mkdirRecursivelySync(path.dirname(cppConfigFilePath)); - fs.writeFileSync(cppConfigFilePath, JSON.stringify(cppConfig, null, 4)); } // Step 3: Open the arduino project at a new vscode window. @@ -769,29 +430,354 @@ Please make sure the folder is not occupied by other procedures .`); this._programmerManager = value; } - private getProgrammerString(): string { - const selectProgrammer = this.programmerManager.currentProgrammer; - if (!selectProgrammer) { - Logger.notifyUserError("getProgrammerString", new Error(constants.messages.NO_PROGRAMMMER_SELECTED)); - return; + /** + * Runs the pre or post build command. + * Usually before one of + * * verify + * * upload + * * upload using programmer + * @param dc Device context prepared during one of the above actions + * @param what "pre" if the pre-build command should be run, "post" if the + * post-build command should be run. + * @returns True if successful, false on error. + */ + protected async runPrePostBuildCommand(dc: DeviceContext, + environment: any, + what: "pre" | "post"): Promise { + const cmdline = what === "pre" + ? dc.prebuild + : dc.postbuild; + + if (!cmdline) { + return true; // Successfully done nothing. + } + + arduinoChannel.info(`Running ${what}-build command: "${cmdline}"`); + let cmd: string; + let args: string[]; + // pre-/post-build commands feature full bash support on UNIX systems. + // On Windows you have full cmd support. + if (os.platform() === "win32") { + args = []; + cmd = cmdline; + } else { + args = ["-c", cmdline]; + cmd = "bash"; + } + try { + await util.spawn(cmd, + args, + { + shell: os.platform() === "win32", + cwd: ArduinoWorkspace.rootPath, + env: {...environment}, + }, + { channel: arduinoChannel.channel }); + } catch (ex) { + const msg = ex.error + ? `${ex.error}` + : ex.code + ? `Exit code = ${ex.code}` + : JSON.stringify(ex); + arduinoChannel.error(`Running ${what}-build command failed: ${os.EOL}${msg}`); + return false; } - return selectProgrammer; + return true; } - private getBoardBuildString(): string { - const selectedBoard = this.boardManager.currentBoard; - if (!selectedBoard) { - Logger.notifyUserError("getBoardBuildString", new Error(constants.messages.NO_BOARD_SELECTED)); - return; - } - return selectedBoard.getBuildConfig(); + /** + * Checks if the arduino cli is being used + * @returns {bool} - true if arduino cli is being use + */ + private useArduinoCli() { + return this._settings.useArduinoCli; + // return VscodeSettings.getInstance().useArduinoCli; } - private async getMainSketch(dc: DeviceContext) { - await dc.resolveMainSketch(); - if (!dc.sketch) { - vscode.window.showErrorMessage("No sketch file was found. Please specify the sketch in the arduino.json file"); - throw new Error("No sketch file was found."); + /** + * Private implementation. Not to be called directly. The wrapper build() + * manages the build state. + * @param buildMode See build() + * @param buildDir See build() + * @see https://github.com/arduino/Arduino/blob/master/build/shared/manpage.adoc + */ + private async _build(buildMode: BuildMode, buildDir?: string): Promise { + const dc = DeviceContext.getInstance(); + const args: string[] = []; + let restoreSerialMonitor: boolean = false; + const verbose = VscodeSettings.getInstance().logLevel === constants.LogLevel.Verbose; + + if (!this.boardManager.currentBoard) { + if (buildMode !== BuildMode.Analyze) { + logger.notifyUserError("boardManager.currentBoard", new Error(constants.messages.NO_BOARD_SELECTED)); + } + return false; + } + const boardDescriptor = this.boardManager.currentBoard.getBuildConfig(); + + if (this.useArduinoCli()) { + args.push("-b", boardDescriptor); + } else { + args.push("--board", boardDescriptor); + } + + if (!ArduinoWorkspace.rootPath) { + vscode.window.showWarningMessage("Workspace doesn't seem to have a folder added to it yet."); + return false; + } + + if (!dc.sketch || !util.fileExistsSync(path.join(ArduinoWorkspace.rootPath, dc.sketch))) { + if (buildMode === BuildMode.Analyze) { + // Analyze runs non interactively + return false; + } + if (!await dc.resolveMainSketch()) { + vscode.window.showErrorMessage("No sketch file was found. Please specify the sketch in the arduino.json file"); + return false; + } + } + + const selectSerial = async () => { + const choice = await vscode.window.showInformationMessage( + "Serial port is not specified. Do you want to select a serial port for uploading?", + "Yes", "No"); + if (choice === "Yes") { + vscode.commands.executeCommand("arduino.selectSerialPort"); + } + } + + if (buildMode === BuildMode.Upload) { + if ((!dc.configuration || !/upload_method=[^=,]*st[^,]*link/i.test(dc.configuration)) && !dc.port) { + await selectSerial(); + return false; + } + + if (this.useArduinoCli()) { + args.push("compile", "--upload"); + } else { + args.push("--upload"); + } + + if (dc.port) { + args.push("--port", dc.port); + } + } else if (buildMode === BuildMode.CliUpload) { + if ((!dc.configuration || !/upload_method=[^=,]*st[^,]*link/i.test(dc.configuration)) && !dc.port) { + await selectSerial(); + return false; + } + + if (!this.useArduinoCli()) { + arduinoChannel.error("This command is only available when using the Arduino CLI"); + return false; + } + + args.push("upload"); + + if (dc.port) { + args.push("--port", dc.port); + } + } else if (buildMode === BuildMode.UploadProgrammer) { + const programmer = this.programmerManager.currentProgrammer; + if (!programmer) { + logger.notifyUserError("programmerManager.currentProgrammer", new Error(constants.messages.NO_PROGRAMMMER_SELECTED)); + return false; + } + if (!dc.port) { + await selectSerial(); + return false; + } + + if (this.useArduinoCli()) { + args.push("compile", + "--upload", + "--programmer", programmer); + } else { + args.push("--upload", + "--useprogrammer", + "--pref", `programmer=arduino:${programmer}`); + } + + args.push("--port", dc.port); + if (!this.useArduinoCli()) { + args.push("--verify"); + } + } else if (buildMode === BuildMode.CliUploadProgrammer) { + const programmer = this.programmerManager.currentProgrammer; + if (!programmer) { + logger.notifyUserError("programmerManager.currentProgrammer", new Error(constants.messages.NO_PROGRAMMMER_SELECTED)); + return false; + } + if (!dc.port) { + await selectSerial(); + return false; + } + if (!this.useArduinoCli()) { + arduinoChannel.error("This command is only available when using the Arduino CLI"); + return false; + } + + args.push("upload", + "--programmer", programmer, + "--port", dc.port); + } else { + if (this.useArduinoCli()) { + args.unshift("compile"); + } else { + args.push("--verify"); + } } + + if (dc.buildPreferences) { + for (const pref of dc.buildPreferences) { + // Note: BuildPrefSetting makes sure that each preference + // value consists of exactly two items (key and value). + args.push("--pref", `${pref[0]}=${pref[1]}`); + } + } + + // We always build verbosely but filter the output based on the settings + + this._settings.useArduinoCli ? args.push("--verbose") : args.push("--verbose-build"); + + if (verbose && !this._settings.useArduinoCli) { + args.push("--verbose-upload"); + } + + await vscode.workspace.saveAll(false); + + // we prepare the channel here since all following code will + // or at leas can possibly output to it + arduinoChannel.show(); + arduinoChannel.start(`${buildMode} sketch '${dc.sketch}'`); + + if (buildDir || dc.output) { + // 2020-02-29, EW: This whole code appears a bit wonky to me. + // What if the user specifies an output directory "../builds/my project" + buildDir = path.resolve(ArduinoWorkspace.rootPath, buildDir || dc.output); + const dirPath = path.dirname(buildDir); + if (!util.directoryExistsSync(dirPath)) { + logger.notifyUserError("InvalidOutPutPath", new Error(constants.messages.INVALID_OUTPUT_PATH + buildDir)); + return false; + } + + if (this.useArduinoCli()) { + args.push("--build-path", buildDir); + + } else { + args.push("--pref", `build.path=${buildDir}`); + } + + arduinoChannel.info(`Please see the build logs in output path: ${buildDir}`); + } else { + const msg = "Output path is not specified. Unable to reuse previously compiled files. Build will be slower. See README."; + arduinoChannel.warning(msg); + } + + // Environment variables passed to pre- and post-build commands + const env = { + VSCA_BUILD_MODE: buildMode, + VSCA_SKETCH: dc.sketch, + VSCA_BOARD: boardDescriptor, + VSCA_WORKSPACE_DIR: ArduinoWorkspace.rootPath, + VSCA_LOG_LEVEL: verbose ? constants.LogLevel.Verbose : constants.LogLevel.Info, + }; + if (dc.port) { + env["VSCA_SERIAL"] = dc.port; + } + if (buildDir) { + env["VSCA_BUILD_DIR"] = buildDir; + } + + // TODO EW: What should we do with pre-/post build commands when running + // analysis? Some could use it to generate/manipulate code which could + // be a prerequisite for a successful build + if (!await this.runPrePostBuildCommand(dc, env, "pre")) { + return false; + } + + // stop serial monitor when everything is prepared and good + // what makes restoring of its previous state easier + if (buildMode === BuildMode.Upload || + buildMode === BuildMode.UploadProgrammer || + buildMode === BuildMode.CliUpload || + buildMode === BuildMode.CliUploadProgrammer) { + restoreSerialMonitor = await SerialMonitor.getInstance().closeSerialMonitor(dc.port); + UsbDetector.getInstance().pauseListening(); + } + + // Push sketch as last argument + args.push(path.join(ArduinoWorkspace.rootPath, dc.sketch)); + + const cocopa = makeCompilerParserContext(dc); + + const cleanup = async (result: "ok" | "error") => { + let ret = true; + if (result === "ok") { + ret = await this.runPrePostBuildCommand(dc, env, "post"); + } + await cocopa.conclude(); + if (buildMode === BuildMode.Upload || buildMode === BuildMode.UploadProgrammer) { + UsbDetector.getInstance().resumeListening(); + if (restoreSerialMonitor) { + await SerialMonitor.getInstance().openSerialMonitor(); + } + } + return ret; + } + const stdoutcb = (line: string) => { + if (cocopa.callback) { + cocopa.callback(line); + } + if (verbose) { + arduinoChannel.channel.append(line); + } + } + const stderrcb = (line: string) => { + if (os.platform() === "win32") { + line = line.trim(); + if (line.length <= 0) { + return; + } + line = line.replace(/(?:\r|\r\n|\n)+/g, os.EOL); + line = `${line}${os.EOL}`; + } + if (!verbose) { + // Don't spill log with spurious info from the backend. This + // list could be fetched from a config file to accommodate + // messages of unknown board packages, newer backend revisions + const filters = [ + /^Picked\sup\sJAVA_TOOL_OPTIONS:\s+/, + /^\d+\d+-\d+-\d+T\d+:\d+:\d+.\d+Z\s(?:INFO|WARN)\s/, + /^(?:DEBUG|TRACE|INFO)\s+/, + ]; + for (const f of filters) { + if (line.match(f)) { + return; + } + } + } + arduinoChannel.channel.append(line); + } + + return await util.spawn( + this._settings.commandPath, + args, + undefined, + { /*channel: arduinoChannel.channel,*/ stdout: stdoutcb, stderr: stderrcb }, + ).then(async () => { + const ret = await cleanup("ok"); + if (ret) { + arduinoChannel.end(`${buildMode} sketch '${dc.sketch}'${os.EOL}`); + } + return ret; + }, async (reason) => { + await cleanup("error"); + const msg = reason.code + ? `Exit with code=${reason.code}` + : JSON.stringify(reason); + arduinoChannel.error(`${buildMode} sketch '${dc.sketch}': ${msg}${os.EOL}`); + return false; + }); } } diff --git a/src/arduino/arduinoContentProvider.ts b/src/arduino/arduinoContentProvider.ts index 6c893eb2..e3dcce7f 100644 --- a/src/arduino/arduinoContentProvider.ts +++ b/src/arduino/arduinoContentProvider.ts @@ -8,20 +8,17 @@ import ArduinoActivator from "../arduinoActivator"; import ArduinoContext from "../arduinoContext"; import * as Constants from "../common/constants"; import * as JSONHelper from "../common/cycle"; +import { DeviceContext } from "../deviceContext"; import * as Logger from "../logger/logger"; import LocalWebServer from "./localWebServer"; -import { VscodeSettings } from "./vscodeSettings"; export class ArduinoContentProvider implements vscode.TextDocumentContentProvider { private _webserver: LocalWebServer; private _onDidChange = new vscode.EventEmitter(); - constructor( - private _extensionPath: string) { - this.initialize(); - } + constructor(private _extensionPath: string) { } - public initialize() { + public async initialize() { this._webserver = new LocalWebServer(this._extensionPath); // Arduino Boards Manager this.addHandlerWithLogger("show-boardmanager", "/boardmanager", (req, res) => this.getHtmlView(req, res)); @@ -50,7 +47,7 @@ export class ArduinoContentProvider implements vscode.TextDocumentContentProvide this.addHandlerWithLogger("load-examples", "/api/examples", async (req, res) => await this.getExamples(req, res)); this.addHandlerWithLogger("open-example", "/api/openexample", (req, res) => this.openExample(req, res), true); - this._webserver.start(); + await this._webserver.start(); } public async provideTextDocumentContent(uri: vscode.Uri): Promise { @@ -207,7 +204,6 @@ export class ArduinoContentProvider implements vscode.TextDocumentContentProvide return res.status(400).send("BAD Request! Missing { libraryPath } parameters!"); } else { try { - await ArduinoContext.arduinoApp.addLibPath(req.body.libraryPath); await ArduinoContext.arduinoApp.includeLibrary(req.body.libraryPath); return res.json({ status: "OK", @@ -262,6 +258,8 @@ export class ArduinoContentProvider implements vscode.TextDocumentContentProvide } else { try { ArduinoContext.boardManager.currentBoard.updateConfig(req.body.configId, req.body.optionId); + const dc = DeviceContext.getInstance(); + dc.configuration = ArduinoContext.boardManager.currentBoard.customConfig; return res.json({ status: "OK", }); diff --git a/src/arduino/arduinoSettings.ts b/src/arduino/arduinoSettings.ts index 58419519..8d994d81 100644 --- a/src/arduino/arduinoSettings.ts +++ b/src/arduino/arduinoSettings.ts @@ -22,6 +22,7 @@ export interface IArduinoSettings { preferencePath: string; defaultBaudRate: number; preferences: Map; + useArduinoCli: boolean; reloadPreferences(): void; } @@ -38,18 +39,21 @@ export class ArduinoSettings implements IArduinoSettings { private _preferences: Map; + private _useArduinoCli: boolean; + public constructor() { } public async initialize() { const platform = os.platform(); this._commandPath = VscodeSettings.getInstance().commandPath; + this._useArduinoCli = VscodeSettings.getInstance().useArduinoCli; await this.tryResolveArduinoPath(); await this.tryGetDefaultBaudRate(); if (platform === "win32") { await this.updateWindowsPath(); if (this._commandPath === "") { - this._commandPath = "arduino_debug.exe"; + this._useArduinoCli ? this._commandPath = "arduino-cli.exe" : this._commandPath = "arduino_debug.exe"; } } else if (platform === "linux") { if (util.directoryExistsSync(path.join(this._arduinoPath, "portable"))) { @@ -150,6 +154,10 @@ export class ArduinoSettings implements IArduinoSettings { return this._preferences; } + public get useArduinoCli() { + return this._useArduinoCli; + } + public get defaultBaudRate() { return this._defaultBaudRate; } diff --git a/src/arduino/board.ts b/src/arduino/board.ts index 39908022..294ce7cf 100644 --- a/src/arduino/board.ts +++ b/src/arduino/board.ts @@ -1,14 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. -import { DeviceContext } from "../deviceContext"; -import { IBoard, IBoardConfigItem, IPlatform } from "./package"; +import { BoardConfigResult, IBoard, IBoardConfigItem, IPlatform } from "./package"; export function parseBoardDescriptor(boardDescriptor: string, plat: IPlatform): Map { const boardLineRegex = /([^\.]+)\.(\S+)=(.+)/; const result = new Map(); - const lines = boardDescriptor.split(/[\r|\r\n|\n]/); + const lines = boardDescriptor.split(/(?:\r|\r\n|\n)/); const menuMap = new Map(); lines.forEach((line) => { @@ -18,7 +17,7 @@ export function parseBoardDescriptor(boardDescriptor: string, plat: IPlatform): } const match = boardLineRegex.exec(line); - if (match && match.length > 3) { + if (match) { if (line.startsWith("menu.")) { menuMap.set(match[2], match[3]); return; @@ -52,15 +51,15 @@ export class Board implements IBoard { this._configItems = []; } - public get board(): string { + public get board() { return this._board; } - public get platform(): IPlatform { + public get platform() { return this._platform; } - public addParameter(key: string, value: string): void { + public addParameter(key: string, value: string) { const match = key.match(MENU_REGEX); if (match) { const existingItem = this._configItems.find((item) => item.id === match[1]); @@ -82,8 +81,7 @@ export class Board implements IBoard { } } } - - public getBuildConfig(): string { + public getBuildConfig() { return `${this.getPackageName()}:${this.platform.architecture}:${this.board}${this.customConfig ? ":" + this.customConfig : ""}`; } @@ -100,36 +98,84 @@ export class Board implements IBoard { } } - public get configItems(): IBoardConfigItem[] { + public get configItems() { return this._configItems; } - public loadConfig(configString: string): void { + public loadConfig(configString: string) { + // An empty or undefined config string resets the configuration + if (!configString) { + this.resetConfig(); + return BoardConfigResult.Success; + } const configSections = configString.split(","); const keyValueRegex = /(\S+)=(\S+)/; - configSections.forEach((configSection) => { - const match = configSection.match(keyValueRegex); - if (match && match.length >= 2) { - this.updateConfig(match[1], match[2]); + let result = BoardConfigResult.Success; + for (const section of configSections) { + const match = section.match(keyValueRegex); + if (!match) { + return BoardConfigResult.InvalidFormat; + } + const r = this.updateConfig(match[1], match[2]); + switch (r) { + case BoardConfigResult.SuccessNoChange: + result = r; + break; + case BoardConfigResult.Success: + break; + default: + return r; } - }); + }; + return result; } - public updateConfig(configId: string, optionId: string): boolean { + /** + * For documentation see the documentation on IBoard.updateConfig(). + */ + public updateConfig(configId: string, optionId: string) { const targetConfig = this._configItems.find((config) => config.id === configId); if (!targetConfig) { - return false; + return BoardConfigResult.InvalidConfigID; + } + // Iterate through all options and ... + for (const o of targetConfig.options) { + // Make sure that we only set valid options, e.g. when loading + // from config files. + if (o.id === optionId) { + if (targetConfig.selectedOption !== optionId) { + targetConfig.selectedOption = optionId; + return BoardConfigResult.Success; + } + return BoardConfigResult.SuccessNoChange; + } } - if (targetConfig.selectedOption !== optionId) { - targetConfig.selectedOption = optionId; - const dc = DeviceContext.getInstance(); - dc.configuration = this.customConfig; - return true; + return BoardConfigResult.InvalidOptionID; + } + + public resetConfig() { + for (const c of this._configItems) { + c.selectedOption = c.options[0].id; } - return false; } public getPackageName() { return this.platform.packageName ? this.platform.packageName : this.platform.package.name; } } + +/** + * Test if two boards are of the same type, i.e. have the same key. + * @param {IBoard | undefined} a A board. + * @param {IBoard | undefined} b And another board. + * @returns {boolean} true if two boards are of the same type, else false. + */ +export function boardEqual(a: IBoard | undefined, + b: IBoard | undefined) { + if (a && b) { + return a.key === b.key; + } else if (a || b) { + return false; + } + return true; +} diff --git a/src/arduino/boardManager.ts b/src/arduino/boardManager.ts index d8267afa..c65c1143 100644 --- a/src/arduino/boardManager.ts +++ b/src/arduino/boardManager.ts @@ -12,8 +12,9 @@ import { arduinoChannel } from "../common/outputChannel"; import { DeviceContext } from "../deviceContext"; import { ArduinoApp } from "./arduino"; import { IArduinoSettings } from "./arduinoSettings"; -import { parseBoardDescriptor } from "./board"; -import { IBoard, IPackage, IPlatform } from "./package"; +import { boardEqual, parseBoardDescriptor } from "./board"; +import { BoardConfigResult, IBoard, IPackage, IPlatform, IProgrammer } from "./package"; +import { parseProgrammerDescriptor } from "./programmer"; import { VscodeSettings } from "./vscodeSettings"; export class BoardManager { @@ -22,6 +23,8 @@ export class BoardManager { private _platforms: IPlatform[]; + private _programmers: Map; + private _installedPlatforms: IPlatform[]; private _boards: Map; @@ -67,15 +70,20 @@ export class BoardManager { // Load default platforms from arduino installation directory and user manually installed platforms. this.loadInstalledPlatforms(); - // Load all supported boards type. + // Load all supported board types this.loadInstalledBoards(); + this.loadInstalledProgrammers(); this.updateStatusBar(); this._boardConfigStatusBar.show(); const dc = DeviceContext.getInstance(); - dc.onDidChange(() => { - this.updateStatusBar(); - }); + dc.onChangeBoard(() => this.onDeviceContextBoardChange()); + dc.onChangeConfiguration(() => this.onDeviceContextConfigurationChange()); + + // load initial board from DeviceContext by emulating + // a board change event. + this.onDeviceContextBoardChange(); + this.updateStatusBar(true); } public async changeBoardType() { @@ -119,13 +127,21 @@ export class BoardManager { public doChangeBoardType(targetBoard: IBoard) { const dc = DeviceContext.getInstance(); - dc.board = targetBoard.key; - this._currentBoard = targetBoard; - dc.configuration = this._currentBoard.customConfig; - this._boardConfigStatusBar.text = targetBoard.name; - this._arduinoApp.addLibPath(null); - this._onBoardTypeChanged.fire(); + if (dc.board === targetBoard.key) { + return; + } + + // Resetting the board first that we don't overwrite the configuration + // of the previous board. + this._currentBoard = null; + // This will cause a configuration changed event which will have no + // effect because no current board is set. + dc.configuration = targetBoard.customConfig; + // This will generate a device context board event which will set the + // correct board and configuration. We know that it will trigger - we + // made sure above that the boards actually differ + dc.board = targetBoard.key; } public get packages(): IPackage[] { @@ -140,6 +156,10 @@ export class BoardManager { return this._boards; } + public get installedProgrammers(): Map { + return this._programmers; + } + public get currentBoard(): IBoard { return this._currentBoard; } @@ -243,23 +263,17 @@ export class BoardManager { this._installedPlatforms.push(existingPlatform); } this.loadInstalledBoardsFromPlatform(existingPlatform); + this.loadInstalledProgrammersFromPlatform(existingPlatform); } } } - public updateStatusBar(show: boolean = true): void { + private updateStatusBar(show: boolean = true): void { if (show) { this._boardConfigStatusBar.show(); - const dc = DeviceContext.getInstance(); - const selectedBoard = this._boards.get(dc.board); - if (selectedBoard) { - this._currentBoard = selectedBoard; - this._boardConfigStatusBar.text = selectedBoard.name; - if (dc.configuration) { - this._currentBoard.loadConfig(dc.configuration); - } + if (this._currentBoard) { + this._boardConfigStatusBar.text = this._currentBoard.name; } else { - this._currentBoard = null; this._boardConfigStatusBar.text = ""; - private static _programmerManager: ProgrammerManager = null; - - private _currentprogrammer: ProgrammerList; - - private _programmervalue: string; + private _programmerValue: string; + private _programmerDisplayName: string; private _programmerStatusBar: vscode.StatusBarItem; constructor(private _settings: IArduinoSettings, private _arduinoApp: ArduinoApp) { - this._programmerStatusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, constants.statusBarPriority.PROGRAMMER); + this._programmerStatusBar = vscode.window.createStatusBarItem( + vscode.StatusBarAlignment.Right, + constants.statusBarPriority.PROGRAMMER, + ); this._programmerStatusBar.command = "arduino.selectProgrammer"; this._programmerStatusBar.tooltip = "Select Programmer"; - this._programmerStatusBar.text = "