From 5a0f93574ab6b5691dcdaee7b94bade597d197f1 Mon Sep 17 00:00:00 2001 From: null Date: Sat, 20 Nov 2021 16:44:47 +0800 Subject: [PATCH 01/48] not rm device macro if no dev pack installed --- src/EIDEProject.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/EIDEProject.ts b/src/EIDEProject.ts index d57ba6a9..4bffc686 100644 --- a/src/EIDEProject.ts +++ b/src/EIDEProject.ts @@ -1724,27 +1724,28 @@ class EIDEProject extends AbstractProject { // project type is ARM if (cConfig instanceof ArmBaseCompileConfigModel) { + const newDevInfo = this.GetPackManager().getCurrentDevInfo(); + // clear old device if (oldDevice) { const dev = this.packManager.getCurrentDevInfo(oldDevice); const define = dev?.define?.split(/ |,/g); - if (define) { + if (define && newDevInfo) { // if we switch device, remove old device macros this.GetConfiguration().CustomDep_RemoveFromDefineList(define); } } // update new device - const deviceInfo = this.GetPackManager().getCurrentDevInfo(); - if (deviceInfo) { + if (newDevInfo) { // update compile options - cConfig.SetKeyValue('cpuType', deviceInfo.core || 'Cortex-M3'); - cConfig.updateStorageLayout(deviceInfo.storageLayout); + cConfig.SetKeyValue('cpuType', newDevInfo.core || 'Cortex-M3'); + cConfig.updateStorageLayout(newDevInfo.storageLayout); // update device, set macro - prjConfig.config.deviceName = deviceInfo.name; - if (deviceInfo.define) { - this.GetConfiguration().CustomDep_AddAllFromDefineList(deviceInfo.define.split(/ |,/g)); + prjConfig.config.deviceName = newDevInfo.name; + if (newDevInfo.define) { + this.GetConfiguration().CustomDep_AddAllFromDefineList(newDevInfo.define.split(/ |,/g)); } } From 498ccc7b692207b1ff9a7fbe61b50c12b9a911ca Mon Sep 17 00:00:00 2001 From: null Date: Sun, 21 Nov 2021 15:16:45 +0800 Subject: [PATCH 02/48] format command name --- package.json | 202 +++++++++++++++++++-------------------- src/OperationExplorer.ts | 12 +-- src/extension.ts | 140 +++++++++++++-------------- 3 files changed, 177 insertions(+), 177 deletions(-) diff --git a/package.json b/package.json index 3cb0e749..af69663d 100644 --- a/package.json +++ b/package.json @@ -465,51 +465,51 @@ "title": "%eide.workspace.make.template%" }, { - "command": "_project.cppcheck.check_all", + "command": "_cl.eide.project.cppcheck.check_all", "title": "%eide.project.run.cppcheck%" }, { - "command": "_project.cppcheck.clear_all", + "command": "_cl.eide.project.cppcheck.clear_all", "title": "%eide.project.clear.cppcheck%" }, { - "command": "_project.source.show_disassembly", + "command": "_cl.eide.project.source.show_disassembly", "title": "%eide.source.show.disassembly%" }, { - "command": "_project.source.show_cmsis_config_wizard", + "command": "_cl.eide.project.source.show_cmsis_config_wizard", "title": "%eide.source.show_cmsis_config_wizard%" }, { - "command": "_project.source.filesystem_folder_add_file", + "command": "_cl.eide.project.source.filesystem_folder_add_file", "title": "%eide.explorer.new.file%" }, { - "command": "_project.source.filesystem_folder_add", + "command": "_cl.eide.project.source.filesystem_folder_add", "title": "%eide.explorer.new.folder%" }, { - "command": "_project.source.virtual_folder_add_file", + "command": "_cl.eide.project.source.virtual_folder_add_file", "title": "%eide.explorer.add.file%" }, { - "command": "_project.source.virtual_folder_add", + "command": "_cl.eide.project.source.virtual_folder_add", "title": "%eide.explorer.add.folder%" }, { - "command": "_project.source.virtual_folder_remove", + "command": "_cl.eide.project.source.virtual_folder_remove", "title": "%eide.explorer.remove.folder%" }, { - "command": "_project.source.virtual_file_remove", + "command": "_cl.eide.project.source.virtual_file_remove", "title": "%eide.explorer.remove.file%" }, { - "command": "_project.source.virtual_folder_rename", + "command": "_cl.eide.project.source.virtual_folder_rename", "title": "%eide.explorer.rename.folder%" }, { - "command": "_project.refresh", + "command": "_cl.eide.project.refresh", "title": "%eide.project.refresh%", "icon": { "dark": "./res/icon/refresh-dark.svg", @@ -517,7 +517,7 @@ } }, { - "command": "_project.sourceRoot.refresh", + "command": "_cl.eide.project.sourceRoot.refresh", "title": "%eide.explorer.root.refresh.folder%", "icon": { "dark": "./res/icon/refresh-dark.svg", @@ -525,7 +525,7 @@ } }, { - "command": "_project.historyRecord", + "command": "_cl.eide.project.historyRecord", "title": "%eide.operation.open.history%", "icon": { "dark": "./res/icon/Note_16x.svg", @@ -533,11 +533,11 @@ } }, { - "command": "_project.clearHistoryRecord", + "command": "_cl.eide.project.clearHistoryRecord", "title": "%eide.operation.clear.history%" }, { - "command": "_project.saveAll", + "command": "_cl.eide.project.saveAll", "title": "%eide.project.save.all%", "icon": { "dark": "./res/icon/SaveAll_16x.svg", @@ -545,7 +545,7 @@ } }, { - "command": "_project.setActive", + "command": "_cl.eide.project.setActive", "title": "%eide.project.active%" }, { @@ -585,15 +585,15 @@ } }, { - "command": "_project.showBuildParams", + "command": "_cl.eide.project.showBuildParams", "title": "%eide.project.show.commands%" }, { - "command": "_project.generate.makefile", + "command": "_cl.eide.project.generate.makefile", "title": "%eide.project.gen.makefile%" }, { - "command": "_project.installCMSISHeaders", + "command": "_cl.eide.project.installCMSISHeaders", "title": "%eide.package.install.cmsis%", "icon": { "dark": "./res/icon/AddBuildQueue_16x.svg", @@ -601,7 +601,7 @@ } }, { - "command": "_project.addSrcDir", + "command": "_cl.eide.project.addSrcDir", "title": "%eide.explorer.root.add.folder%", "icon": { "dark": "./res/icon/AddFolder_16x.svg", @@ -609,7 +609,7 @@ } }, { - "command": "_project.removeSrcDir", + "command": "_cl.eide.project.removeSrcDir", "title": "%eide.explorer.root.remove.folder%", "icon": { "dark": "./res/icon/TestCoveredFailing_16x.svg", @@ -617,7 +617,7 @@ } }, { - "command": "_project.close", + "command": "_cl.eide.project.close", "title": "%eide.project.close%", "icon": { "dark": "./res/icon/TestCoveredFailing_16x.svg", @@ -625,7 +625,7 @@ } }, { - "command": "_project.addPackage", + "command": "_cl.eide.project.addPackage", "title": "%eide.package.install%", "icon": { "dark": "./res/icon/Add_16xMD.svg", @@ -633,7 +633,7 @@ } }, { - "command": "_project.removePackage", + "command": "_cl.eide.project.removePackage", "title": "%eide.package.remove%", "icon": { "dark": "./res/icon/TestCoveredFailing_16x.svg", @@ -641,7 +641,7 @@ } }, { - "command": "_project.setDevice", + "command": "_cl.eide.project.setDevice", "title": "%eide.package.select.device%", "icon": { "dark": "./res/icon/FieldAdded_16x.svg", @@ -649,7 +649,7 @@ } }, { - "command": "_project.exportXml", + "command": "_cl.eide.project.exportXml", "title": "%eide.project.export.keil%", "icon": { "dark": "./res/icon/ExportFile_16x.svg", @@ -657,7 +657,7 @@ } }, { - "command": "_project.modifyCompileConfig", + "command": "_cl.eide.project.modifyCompileConfig", "title": "%eide.item.modify%", "icon": { "dark": "./res/icon/Pen4_16x.svg", @@ -665,7 +665,7 @@ } }, { - "command": "_project.switchToolchain", + "command": "_cl.eide.project.switchToolchain", "title": "%eide.builder.switch%", "icon": { "dark": "./res/icon/SwitchSourceOrTarget_16x.svg", @@ -673,7 +673,7 @@ } }, { - "command": "_project.switchUploader", + "command": "_cl.eide.project.switchUploader", "title": "%eide.flash.switch%", "icon": { "dark": "./res/icon/SwitchSourceOrTarget_16x.svg", @@ -681,7 +681,7 @@ } }, { - "command": "_project.modifyUploadConfig", + "command": "_cl.eide.project.modifyUploadConfig", "title": "%eide.item.modify%", "icon": { "dark": "./res/icon/Pen4_16x.svg", @@ -689,7 +689,7 @@ } }, { - "command": "_project.modifyOtherSettings", + "command": "_cl.eide.project.modifyOtherSettings", "title": "%eide.item.modify%", "icon": { "dark": "./res/icon/Pen4_16x.svg", @@ -697,7 +697,7 @@ } }, { - "command": "_project.addIncludeDir", + "command": "_cl.eide.project.addIncludeDir", "title": "%eide.deps.include.add%", "icon": { "dark": "./res/icon/Add_16xMD.svg", @@ -705,7 +705,7 @@ } }, { - "command": "_project.addLibDir", + "command": "_cl.eide.project.addLibDir", "title": "%eide.deps.inclib.add%", "icon": { "dark": "./res/icon/Add_16xMD.svg", @@ -713,7 +713,7 @@ } }, { - "command": "_project.addDefine", + "command": "_cl.eide.project.addDefine", "title": "%eide.deps.macro.add%", "icon": { "dark": "./res/icon/Add_16xMD.svg", @@ -721,7 +721,7 @@ } }, { - "command": "_project.showIncludeDir", + "command": "_cl.eide.project.showIncludeDir", "title": "%eide.deps.include.show%", "icon": { "dark": "./res/icon/eye_16x_dark.svg", @@ -729,7 +729,7 @@ } }, { - "command": "_project.showLibDir", + "command": "_cl.eide.project.showLibDir", "title": "%eide.deps.inclib.show%", "icon": { "dark": "./res/icon/eye_16x_dark.svg", @@ -737,7 +737,7 @@ } }, { - "command": "_project.showDefine", + "command": "_cl.eide.project.showDefine", "title": "%eide.deps.macro.show%", "icon": { "dark": "./res/icon/eye_16x_dark.svg", @@ -745,7 +745,7 @@ } }, { - "command": "_project.excludeSource", + "command": "_cl.eide.project.excludeSource", "title": "%eide.explorer.exclude.file%", "icon": { "dark": "./res/icon/StatusNo_16x.svg", @@ -753,7 +753,7 @@ } }, { - "command": "_project.unexcludeSource", + "command": "_cl.eide.project.unexcludeSource", "title": "%eide.explorer.include.file%", "icon": { "dark": "./res/icon/Add_16xMD.svg", @@ -761,7 +761,7 @@ } }, { - "command": "_project.excludeFolder", + "command": "_cl.eide.project.excludeFolder", "title": "%eide.explorer.exclude.folder%", "icon": { "dark": "./res/icon/StatusNo_16x.svg", @@ -769,7 +769,7 @@ } }, { - "command": "_project.unexcludeFolder", + "command": "_cl.eide.project.unexcludeFolder", "title": "%eide.explorer.include.folder%", "icon": { "dark": "./res/icon/Add_16xMD.svg", @@ -777,7 +777,7 @@ } }, { - "command": "_project.removeDependenceItem", + "command": "_cl.eide.project.removeDependenceItem", "title": "%eide.item.remove%", "icon": { "dark": "./res/icon/TestCoveredFailing_16x.svg", @@ -785,7 +785,7 @@ } }, { - "command": "_project.importDependenceFromPack", + "command": "_cl.eide.project.importDependenceFromPack", "title": "%eide.package.comp.install%", "icon": { "dark": "./res/icon/AddToCollection_16x.svg", @@ -793,7 +793,7 @@ } }, { - "command": "_project.removeDependenceFromPack", + "command": "_cl.eide.project.removeDependenceFromPack", "title": "%eide.package.comp.uninstall%", "icon": { "dark": "./res/icon/TestCoveredFailing_16x.svg", @@ -801,7 +801,7 @@ } }, { - "command": "_project.copyItemValue", + "command": "_cl.eide.project.copyItemValue", "title": "%eide.item.copy%", "icon": { "dark": "./res/icon/CopyToClipboard_16x.svg", @@ -809,7 +809,7 @@ } }, { - "command": "_project.switchMode", + "command": "_cl.eide.project.switchMode", "title": "%eide.project.switch.target%", "icon": { "dark": "./res/icon/SwitchSourceOrTarget_16x.svg", @@ -817,7 +817,7 @@ } }, { - "command": "_project.exportAsTemplate", + "command": "_cl.eide.project.exportAsTemplate", "title": "%eide.project.export.template%", "icon": { "dark": "./res/icon/TableToFile_16x.svg", @@ -862,7 +862,7 @@ "when": "cl.eide.projectActived && !isInDiffEditor" }, { - "command": "_project.cppcheck.check_all", + "command": "_cl.eide.project.cppcheck.check_all", "key": "ctrl+alt+c", "when": "cl.eide.projectActived" } @@ -885,21 +885,21 @@ "when": "view == Project && cl.eide.isWorkspaceProject" }, { - "command": "_project.refresh", + "command": "_cl.eide.project.refresh", "group": "navigation", "when": "view == Project" }, { - "command": "_project.historyRecord", + "command": "_cl.eide.project.historyRecord", "group": "navigation", "when": "view == Operation" }, { - "command": "_project.clearHistoryRecord", + "command": "_cl.eide.project.clearHistoryRecord", "when": "view == Operation" }, { - "command": "_project.saveAll", + "command": "_cl.eide.project.saveAll", "group": "navigation", "when": "view == Project" } @@ -923,12 +923,12 @@ ], "editor/context": [ { - "command": "_project.source.show_disassembly", + "command": "_cl.eide.project.source.show_disassembly", "group": "commands", "when": "resourceLangId =~ /^c$|^cpp$/ && cl.eide.projectActived && !config.EIDE.Option.DisableEditorContextMenu" }, { - "command": "_project.source.show_cmsis_config_wizard", + "command": "_cl.eide.project.source.show_cmsis_config_wizard", "group": "commands", "when": "resourceLangId =~ /^c$|^cpp$/ && !config.EIDE.Option.DisableEditorContextMenu" } @@ -940,90 +940,90 @@ "when": "resourceLangId =~ /^c$|^cpp$/ && cl.eide.projectActived && !config.EIDE.Option.DisableExplorerContextMenu" }, { - "command": "_project.source.show_disassembly", + "command": "_cl.eide.project.source.show_disassembly", "group": "commands", "when": "resourceLangId =~ /^c$|^cpp$/ && cl.eide.projectActived && !config.EIDE.Option.DisableExplorerContextMenu" }, { - "command": "_project.source.show_cmsis_config_wizard", + "command": "_cl.eide.project.source.show_cmsis_config_wizard", "group": "commands", "when": "resourceLangId =~ /^c$|^cpp$/ && !config.EIDE.Option.DisableExplorerContextMenu" } ], "view/item/context": [ { - "command": "_project.cppcheck.check_all", + "command": "_cl.eide.project.cppcheck.check_all", "when": "viewItem == SOLUTION && view == Project" }, { - "command": "_project.cppcheck.clear_all", + "command": "_cl.eide.project.cppcheck.clear_all", "when": "viewItem == SOLUTION && view == Project" }, { - "command": "_project.source.filesystem_folder_add_file", + "command": "_cl.eide.project.source.filesystem_folder_add_file", "when": "viewItem == FOLDER || viewItem == FOLDER_ROOT && view == Project" }, { - "command": "_project.source.filesystem_folder_add", + "command": "_cl.eide.project.source.filesystem_folder_add", "when": "viewItem == FOLDER || viewItem == FOLDER_ROOT && view == Project" }, { - "command": "_project.source.virtual_folder_add_file", + "command": "_cl.eide.project.source.virtual_folder_add_file", "when": "viewItem == V_FOLDER_ROOT || viewItem == V_FOLDER || viewItem == V_EXCFOLDER && view == Project" }, { - "command": "_project.source.virtual_folder_add", + "command": "_cl.eide.project.source.virtual_folder_add", "when": "viewItem == V_FOLDER_ROOT || viewItem == V_FOLDER || viewItem == V_EXCFOLDER && view == Project" }, { - "command": "_project.source.virtual_folder_remove", + "command": "_cl.eide.project.source.virtual_folder_remove", "when": "viewItem == V_FOLDER_ROOT || viewItem == V_FOLDER || viewItem == V_EXCFOLDER && view == Project" }, { - "command": "_project.source.virtual_folder_rename", + "command": "_cl.eide.project.source.virtual_folder_rename", "when": "viewItem == V_FOLDER_ROOT || viewItem == V_FOLDER || viewItem == V_EXCFOLDER && view == Project" }, { - "command": "_project.source.virtual_file_remove", + "command": "_cl.eide.project.source.virtual_file_remove", "when": "viewItem == V_FILE_ITEM || viewItem == V_EXCFILE_ITEM && view == Project" }, { - "command": "_project.addPackage", + "command": "_cl.eide.project.addPackage", "group": "inline", "when": "viewItem == PACK && view == Project" }, { - "command": "_project.removePackage", + "command": "_cl.eide.project.removePackage", "group": "inline", "when": "viewItem == PACK_GROUP && view == Project" }, { - "command": "_project.setDevice", + "command": "_cl.eide.project.setDevice", "group": "inline", "when": "viewItem == PACK_GROUP && view == Project" }, { - "command": "_project.addPackage", + "command": "_cl.eide.project.addPackage", "when": "viewItem == PACK && view == Project" }, { - "command": "_project.installCMSISHeaders", + "command": "_cl.eide.project.installCMSISHeaders", "when": "viewItem == PACK && view == Project" }, { - "command": "_project.setActive", + "command": "_cl.eide.project.setActive", "when": "viewItem == SOLUTION && view == Project && cl.eide.enable.active" }, { - "command": "_project.switchMode", + "command": "_cl.eide.project.switchMode", "when": "viewItem == SOLUTION && view == Project" }, { - "command": "_project.exportAsTemplate", + "command": "_cl.eide.project.exportAsTemplate", "when": "viewItem == SOLUTION && view == Project" }, { - "command": "_project.exportXml", + "command": "_cl.eide.project.exportXml", "when": "viewItem == SOLUTION && view == Project" }, { @@ -1042,11 +1042,11 @@ "when": "viewItem == SOLUTION && view == Project" }, { - "command": "_project.showBuildParams", + "command": "_cl.eide.project.showBuildParams", "when": "viewItem == SOLUTION && view == Project" }, { - "command": "_project.generate.makefile", + "command": "_cl.eide.project.generate.makefile", "when": "viewItem == SOLUTION && view == Project" }, { @@ -1055,120 +1055,120 @@ "when": "viewItem == SOLUTION && view == Project" }, { - "command": "_project.close", + "command": "_cl.eide.project.close", "when": "viewItem == SOLUTION && view == Project" }, { - "command": "_project.excludeSource", + "command": "_cl.eide.project.excludeSource", "group": "inline", "when": "viewItem == FILE_ITEM || viewItem == V_FILE_ITEM && view == Project" }, { - "command": "_project.unexcludeSource", + "command": "_cl.eide.project.unexcludeSource", "group": "inline", "when": "viewItem == EXCFILE_ITEM || viewItem == V_EXCFILE_ITEM && view == Project" }, { - "command": "_project.excludeFolder", + "command": "_cl.eide.project.excludeFolder", "group": "inline", "when": "viewItem == FOLDER || viewItem == V_FOLDER || viewItem == V_FOLDER_ROOT && view == Project" }, { - "command": "_project.unexcludeFolder", + "command": "_cl.eide.project.unexcludeFolder", "group": "inline", "when": "viewItem == EXCFOLDER || viewItem == V_EXCFOLDER && view == Project" }, { - "command": "_project.addSrcDir", + "command": "_cl.eide.project.addSrcDir", "group": "inline", "when": "viewItem == PROJECT && view == Project" }, { - "command": "_project.addSrcDir", + "command": "_cl.eide.project.addSrcDir", "when": "viewItem == PROJECT && view == Project" }, { - "command": "_project.sourceRoot.refresh", + "command": "_cl.eide.project.sourceRoot.refresh", "group": "inline", "when": "viewItem == FOLDER_ROOT_DEPS || viewItem == FOLDER_ROOT || viewItem == V_FOLDER_ROOT && view == Project" }, { - "command": "_project.removeSrcDir", + "command": "_cl.eide.project.removeSrcDir", "group": "inline", "when": "viewItem == FOLDER_ROOT && view == Project" }, { - "command": "_project.switchToolchain", + "command": "_cl.eide.project.switchToolchain", "group": "inline", "when": "viewItem == COMPILE_CONFIGURATION && view == Project" }, { - "command": "_project.switchUploader", + "command": "_cl.eide.project.switchUploader", "group": "inline", "when": "viewItem == UPLOAD_OPTION_C51 || viewItem == UPLOAD_OPTION" }, { - "command": "_project.modifyCompileConfig", + "command": "_cl.eide.project.modifyCompileConfig", "group": "inline", "when": "viewItem == COMPILE_CONFIGURATION_ITEM && view == Project" }, { - "command": "_project.modifyUploadConfig", + "command": "_cl.eide.project.modifyUploadConfig", "group": "inline", "when": "viewItem == UPLOAD_OPTION_ITEM && view == Project" }, { - "command": "_project.modifyOtherSettings", + "command": "_cl.eide.project.modifyOtherSettings", "group": "inline", "when": "viewItem == SETTINGS_ITEM && view == Project" }, { - "command": "_project.addIncludeDir", + "command": "_cl.eide.project.addIncludeDir", "group": "inline", "when": "viewItem == INC_GROUP && view == Project" }, { - "command": "_project.showIncludeDir", + "command": "_cl.eide.project.showIncludeDir", "group": "inline", "when": "viewItem == INC_GROUP && view == Project" }, { - "command": "_project.addLibDir", + "command": "_cl.eide.project.addLibDir", "group": "inline", "when": "viewItem == LIB_GROUP && view == Project" }, { - "command": "_project.showLibDir", + "command": "_cl.eide.project.showLibDir", "group": "inline", "when": "viewItem == LIB_GROUP && view == Project" }, { - "command": "_project.addDefine", + "command": "_cl.eide.project.addDefine", "group": "inline", "when": "viewItem == DEFINE_GROUP && view == Project" }, { - "command": "_project.showDefine", + "command": "_cl.eide.project.showDefine", "group": "inline", "when": "viewItem == DEFINE_GROUP && view == Project" }, { - "command": "_project.removeDependenceItem", + "command": "_cl.eide.project.removeDependenceItem", "group": "inline", "when": "viewItem == INC_ITEM || viewItem == DEFINE_ITEM || viewItem == LIB_ITEM || viewItem == SOURCE_ITEM && view == Project" }, { - "command": "_project.copyItemValue", + "command": "_cl.eide.project.copyItemValue", "group": "inline", "when": "viewItem == EXCFILE_ITEM || viewItem == FILE_ITEM || viewItem == SRCREF_FILE_ITEM || viewItem == ITEM || viewItem == DEPENDENCE_ITEM || viewItem == INC_ITEM || viewItem == DEFINE_ITEM || viewItem == LIB_ITEM || viewItem == SOURCE_ITEM && view == Project" }, { - "command": "_project.importDependenceFromPack", + "command": "_cl.eide.project.importDependenceFromPack", "group": "inline", "when": "viewItem == COMPONENT_GROUP && view == Project" }, { - "command": "_project.removeDependenceFromPack", + "command": "_cl.eide.project.removeDependenceFromPack", "group": "inline", "when": "viewItem == ACTIVED_GROUP && view == Project" } diff --git a/src/OperationExplorer.ts b/src/OperationExplorer.ts index a0893b95..de751971 100644 --- a/src/OperationExplorer.ts +++ b/src/OperationExplorer.ts @@ -195,7 +195,7 @@ export class OperationExplorer { label: create_project, command: { title: create_project, - command: 'Operation.Create' + command: '_cl.eide.Operation.Create' }, tooltip: create_project_hit, iconPath: { @@ -209,7 +209,7 @@ export class OperationExplorer { label: view_str$import_project, command: { title: view_str$import_project, - command: 'Operation.Import' + command: '_cl.eide.Operation.Import' }, tooltip: import_project_hit, iconPath: { @@ -223,7 +223,7 @@ export class OperationExplorer { label: open_project, command: { title: open_project, - command: 'Operation.Open' + command: '_cl.eide.Operation.Open' }, tooltip: open_project_hit, iconPath: { @@ -237,7 +237,7 @@ export class OperationExplorer { label: view_str$operation$open_serialport, command: { title: view_str$operation$open_serialport, - command: 'Operation.OpenSerialPortMonitor' + command: '_cl.eide.Operation.OpenSerialPortMonitor' }, tooltip: view_str$operation$open_serialport, iconPath: { @@ -256,7 +256,7 @@ export class OperationExplorer { label: view_str$operation$setToolchainPath, command: { title: view_str$operation$setToolchainPath, - command: 'Operation.SetToolchainPath' + command: '_cl.eide.Operation.SetToolchainPath' }, tooltip: view_str$operation$setToolchainPath, iconPath: { @@ -273,7 +273,7 @@ export class OperationExplorer { label: view_str$operation$openSettings, command: { title: view_str$operation$openSettings, - command: 'Operation.openSettings' + command: '_cl.eide.Operation.openSettings' }, tooltip: view_str$operation$openSettings, iconPath: { diff --git a/src/extension.ts b/src/extension.ts index 625f29a4..bc323642 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -77,18 +77,17 @@ export async function activate(context: vscode.ExtensionContext) { subscriptions.push(vscode.commands.registerCommand('eide.c51ToSdcc', () => c51ToSDCC())); subscriptions.push(vscode.commands.registerCommand('eide.ReloadJlinkDevs', () => reloadJlinkDevices())); subscriptions.push(vscode.commands.registerCommand('eide.ReloadStm8Devs', () => reloadStm8Devices())); - - // other commands subscriptions.push(vscode.commands.registerCommand('eide.selectBaudrate', () => onSelectSerialBaudrate())); const operationExplorer = new OperationExplorer(context); - subscriptions.push(vscode.commands.registerCommand('Operation.Open', () => operationExplorer.OnOpenProject())); - subscriptions.push(vscode.commands.registerCommand('Operation.Create', () => operationExplorer.OnCreateProject())); - subscriptions.push(vscode.commands.registerCommand('Operation.Import', () => operationExplorer.OnImportProject())); - subscriptions.push(vscode.commands.registerCommand('Operation.SetToolchainPath', () => operationExplorer.OnSetToolchainPath())); - subscriptions.push(vscode.commands.registerCommand('Operation.OpenSerialPortMonitor', () => operationExplorer.onOpenSerialPortMonitor())); - subscriptions.push(vscode.commands.registerCommand('Operation.openSettings', () => SettingManager.jumpToSettings('@ext:cl.eide'))); - /* export commands */ + subscriptions.push(vscode.commands.registerCommand('_cl.eide.Operation.Open', () => operationExplorer.OnOpenProject())); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.Operation.Create', () => operationExplorer.OnCreateProject())); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.Operation.Import', () => operationExplorer.OnImportProject())); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.Operation.SetToolchainPath', () => operationExplorer.OnSetToolchainPath())); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.Operation.OpenSerialPortMonitor', () => operationExplorer.onOpenSerialPortMonitor())); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.Operation.openSettings', () => SettingManager.jumpToSettings('@ext:cl.eide'))); + + // public cmds subscriptions.push(vscode.commands.registerCommand('eide.operation.install_toolchain', () => operationExplorer.OnSetToolchainPath())); subscriptions.push(vscode.commands.registerCommand('eide.operation.import_project', () => operationExplorer.OnImportProject())); subscriptions.push(vscode.commands.registerCommand('eide.operation.new_project', () => operationExplorer.OnCreateProject())); @@ -100,74 +99,75 @@ export async function activate(context: vscode.ExtensionContext) { subscriptions.push(vscode.commands.registerCommand('_cl.eide.workspace.open.config', () => projectExplorer.openWorkspaceConfig())); subscriptions.push(vscode.commands.registerCommand('_cl.eide.workspace.make.template', (item) => projectExplorer.ExportToTemplate(undefined, true))); + // public cmds subscriptions.push(vscode.commands.registerCommand('eide.project.rebuild', (item) => projectExplorer.BuildSolution(item))); subscriptions.push(vscode.commands.registerCommand('eide.project.build', (item) => projectExplorer.BuildSolution(item, { useFastMode: true }))); subscriptions.push(vscode.commands.registerCommand('eide.project.clean', (item) => projectExplorer.BuildClean(item))); subscriptions.push(vscode.commands.registerCommand('eide.project.uploadToDevice', (item) => projectExplorer.UploadToDevice(item))); subscriptions.push(vscode.commands.registerCommand('eide.reinstall.binaries', () => checkAndInstallBinaries(context, true))); - subscriptions.push(vscode.commands.registerCommand('_project.historyRecord', () => projectExplorer.openHistoryRecords())); - subscriptions.push(vscode.commands.registerCommand('_project.clearHistoryRecord', () => projectExplorer.clearAllHistoryRecords())); - subscriptions.push(vscode.commands.registerCommand('_project.showBuildParams', (item) => projectExplorer.BuildSolution(item, { useDebug: true }))); - subscriptions.push(vscode.commands.registerCommand('_project.generate.makefile', (item) => projectExplorer.generateMakefile(item))); - - subscriptions.push(vscode.commands.registerCommand('_project.setActive', (item) => projectExplorer.setActiveProject(item))); - subscriptions.push(vscode.commands.registerCommand('_project.close', (item) => projectExplorer.Close(item))); - subscriptions.push(vscode.commands.registerCommand('_project.saveAll', () => projectExplorer.SaveAll())); - subscriptions.push(vscode.commands.registerCommand('_project.refresh', () => projectExplorer.Refresh())); - subscriptions.push(vscode.commands.registerCommand('_project.switchMode', (item) => projectExplorer.switchTarget(item))); - subscriptions.push(vscode.commands.registerCommand('_project.exportAsTemplate', (item) => projectExplorer.ExportToTemplate(item))); - - subscriptions.push(vscode.commands.registerCommand('_project.addSrcDir', (item) => projectExplorer.AddSrcDir(item))); - subscriptions.push(vscode.commands.registerCommand('_project.removeSrcDir', (item) => projectExplorer.RemoveSrcDir(item))); - subscriptions.push(vscode.commands.registerCommand('_project.sourceRoot.refresh', (item) => projectExplorer.refreshSrcRoot(item))); - - subscriptions.push(vscode.commands.registerCommand('_project.source.filesystem_folder_add_file', (item) => projectExplorer.fs_folderAddFile(item))); - subscriptions.push(vscode.commands.registerCommand('_project.source.filesystem_folder_add', (item) => projectExplorer.fs_folderAdd(item))); - - subscriptions.push(vscode.commands.registerCommand('_project.source.virtual_folder_add_file', (item) => projectExplorer.Virtual_folderAddFile(item))); - subscriptions.push(vscode.commands.registerCommand('_project.source.virtual_folder_add', (item) => projectExplorer.Virtual_folderAdd(item))); - subscriptions.push(vscode.commands.registerCommand('_project.source.virtual_folder_remove', (item) => projectExplorer.Virtual_removeFolder(item))); - subscriptions.push(vscode.commands.registerCommand('_project.source.virtual_folder_rename', (item) => projectExplorer.Virtual_renameFolder(item))); - subscriptions.push(vscode.commands.registerCommand('_project.source.virtual_file_remove', (item) => projectExplorer.Virtual_removeFile(item))); - - subscriptions.push(vscode.commands.registerCommand('_project.excludeSource', (item) => projectExplorer.ExcludeSourceFile(item))); - subscriptions.push(vscode.commands.registerCommand('_project.unexcludeSource', (item) => projectExplorer.UnexcludeSourceFile(item))); - subscriptions.push(vscode.commands.registerCommand('_project.excludeFolder', (item) => projectExplorer.ExcludeFolder(item))); - subscriptions.push(vscode.commands.registerCommand('_project.unexcludeFolder', (item) => projectExplorer.UnexcludeFolder(item))); - - subscriptions.push(vscode.commands.registerCommand('_project.installCMSISHeaders', (item) => projectExplorer.installCMSISHeaders(item))); - subscriptions.push(vscode.commands.registerCommand('_project.removePackage', (item) => projectExplorer.UninstallKeilPackage(item))); - subscriptions.push(vscode.commands.registerCommand('_project.addPackage', (item) => projectExplorer.InstallKeilPackage(item.val.projectIndex))); - subscriptions.push(vscode.commands.registerCommand('_project.exportXml', (item) => projectExplorer.ExportKeilXml(item.val.projectIndex))); - subscriptions.push(vscode.commands.registerCommand('_project.setDevice', (item) => projectExplorer.SetDevice(item.val.projectIndex))); - subscriptions.push(vscode.commands.registerCommand('_project.modifyCompileConfig', (item) => projectExplorer.ModifyCompileConfig(item))); - subscriptions.push(vscode.commands.registerCommand('_project.switchToolchain', (item) => projectExplorer.onSwitchCompileTools(item))); - - subscriptions.push(vscode.commands.registerCommand('_project.modifyUploadConfig', (item) => projectExplorer.ModifyUploadConfig(item))); - subscriptions.push(vscode.commands.registerCommand('_project.switchUploader', (item) => projectExplorer.switchUploader(item))); - - subscriptions.push(vscode.commands.registerCommand('_project.addIncludeDir', (item) => projectExplorer.AddIncludeDir(item.val.projectIndex))); - subscriptions.push(vscode.commands.registerCommand('_project.addDefine', (item) => projectExplorer.AddDefine(item.val.projectIndex))); - subscriptions.push(vscode.commands.registerCommand('_project.addLibDir', (item) => projectExplorer.AddLibDir(item.val.projectIndex))); - subscriptions.push(vscode.commands.registerCommand('_project.showIncludeDir', (item) => projectExplorer.showIncludeDir(item.val.projectIndex))); - subscriptions.push(vscode.commands.registerCommand('_project.showDefine', (item) => projectExplorer.showDefine(item.val.projectIndex))); - subscriptions.push(vscode.commands.registerCommand('_project.showLibDir', (item) => projectExplorer.showLibDir(item.val.projectIndex))); - - subscriptions.push(vscode.commands.registerCommand('_project.modifyOtherSettings', (item) => projectExplorer.ModifyOtherSettings(item))); - - subscriptions.push(vscode.commands.registerCommand('_project.removeDependenceItem', (item) => projectExplorer.RemoveDependenceItem(item))); - subscriptions.push(vscode.commands.registerCommand('_project.importDependenceFromPack', (item) => projectExplorer.ImportPackageDependence(item))); - subscriptions.push(vscode.commands.registerCommand('_project.removeDependenceFromPack', (item) => projectExplorer.RemovePackageDependence(item))); - - subscriptions.push(vscode.commands.registerCommand('_project.copyItemValue', (item) => projectExplorer.CopyItemValue(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.historyRecord', () => projectExplorer.openHistoryRecords())); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.clearHistoryRecord', () => projectExplorer.clearAllHistoryRecords())); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.showBuildParams', (item) => projectExplorer.BuildSolution(item, { useDebug: true }))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.generate.makefile', (item) => projectExplorer.generateMakefile(item))); + + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.setActive', (item) => projectExplorer.setActiveProject(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.close', (item) => projectExplorer.Close(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.saveAll', () => projectExplorer.SaveAll())); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.refresh', () => projectExplorer.Refresh())); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.switchMode', (item) => projectExplorer.switchTarget(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.exportAsTemplate', (item) => projectExplorer.ExportToTemplate(item))); + + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.addSrcDir', (item) => projectExplorer.AddSrcDir(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.removeSrcDir', (item) => projectExplorer.RemoveSrcDir(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.sourceRoot.refresh', (item) => projectExplorer.refreshSrcRoot(item))); + + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.filesystem_folder_add_file', (item) => projectExplorer.fs_folderAddFile(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.filesystem_folder_add', (item) => projectExplorer.fs_folderAdd(item))); + + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.virtual_folder_add_file', (item) => projectExplorer.Virtual_folderAddFile(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.virtual_folder_add', (item) => projectExplorer.Virtual_folderAdd(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.virtual_folder_remove', (item) => projectExplorer.Virtual_removeFolder(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.virtual_folder_rename', (item) => projectExplorer.Virtual_renameFolder(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.virtual_file_remove', (item) => projectExplorer.Virtual_removeFile(item))); + + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.excludeSource', (item) => projectExplorer.ExcludeSourceFile(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.unexcludeSource', (item) => projectExplorer.UnexcludeSourceFile(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.excludeFolder', (item) => projectExplorer.ExcludeFolder(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.unexcludeFolder', (item) => projectExplorer.UnexcludeFolder(item))); + + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.installCMSISHeaders', (item) => projectExplorer.installCMSISHeaders(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.removePackage', (item) => projectExplorer.UninstallKeilPackage(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.addPackage', (item) => projectExplorer.InstallKeilPackage(item.val.projectIndex))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.exportXml', (item) => projectExplorer.ExportKeilXml(item.val.projectIndex))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.setDevice', (item) => projectExplorer.SetDevice(item.val.projectIndex))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.modifyCompileConfig', (item) => projectExplorer.ModifyCompileConfig(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.switchToolchain', (item) => projectExplorer.onSwitchCompileTools(item))); + + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.modifyUploadConfig', (item) => projectExplorer.ModifyUploadConfig(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.switchUploader', (item) => projectExplorer.switchUploader(item))); + + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.addIncludeDir', (item) => projectExplorer.AddIncludeDir(item.val.projectIndex))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.addDefine', (item) => projectExplorer.AddDefine(item.val.projectIndex))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.addLibDir', (item) => projectExplorer.AddLibDir(item.val.projectIndex))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.showIncludeDir', (item) => projectExplorer.showIncludeDir(item.val.projectIndex))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.showDefine', (item) => projectExplorer.showDefine(item.val.projectIndex))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.showLibDir', (item) => projectExplorer.showLibDir(item.val.projectIndex))); + + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.modifyOtherSettings', (item) => projectExplorer.ModifyOtherSettings(item))); + + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.removeDependenceItem', (item) => projectExplorer.RemoveDependenceItem(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.importDependenceFromPack', (item) => projectExplorer.ImportPackageDependence(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.removeDependenceFromPack', (item) => projectExplorer.RemovePackageDependence(item))); + + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.copyItemValue', (item) => projectExplorer.CopyItemValue(item))); /* other project tools */ - subscriptions.push(vscode.commands.registerCommand('_project.source.show_disassembly', (url) => projectExplorer.showDisassembly(url))); - subscriptions.push(vscode.commands.registerCommand('_project.source.show_cmsis_config_wizard', (url) => projectExplorer.showCmsisConfigWizard(url))); - //subscriptions.push(vscode.commands.registerCommand('_project.cppcheck.check_file', (url) => projectExplorer.cppcheckFile(url))); - subscriptions.push(vscode.commands.registerCommand('_project.cppcheck.check_all', (item) => projectExplorer.cppcheckProject(item))); - subscriptions.push(vscode.commands.registerCommand('_project.cppcheck.clear_all', (item) => projectExplorer.clearCppcheckDiagnostic())); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.show_disassembly', (url) => projectExplorer.showDisassembly(url))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.show_cmsis_config_wizard', (url) => projectExplorer.showCmsisConfigWizard(url))); + //subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.cppcheck.check_file', (url) => projectExplorer.cppcheckFile(url))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.cppcheck.check_all', (item) => projectExplorer.cppcheckProject(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.cppcheck.clear_all', (item) => projectExplorer.clearCppcheckDiagnostic())); operationExplorer.on('request_open_project', (fsPath) => projectExplorer.emit('request_open_project', fsPath)); operationExplorer.on('request_create_project', (option) => projectExplorer.emit('request_create_project', option)); @@ -227,7 +227,7 @@ async function onSelectSerialBaudrate() { '4800', '9600', '14400', '19200', '28800', '38400', '57600', '115200', '230400', - '460800', '576000' + '460800', '576000', '921600' ]; const baudrate = await vscode.window.showQuickPick(baudList, { From 81a13e8d57bda5d22e4cd07dae34130b09ba5949 Mon Sep 17 00:00:00 2001 From: null Date: Sun, 21 Nov 2021 16:41:14 +0800 Subject: [PATCH 03/48] rm temp file after read jlink dev list --- src/ResManager.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/ResManager.ts b/src/ResManager.ts index 3c70dc01..17b2b54a 100644 --- a/src/ResManager.ts +++ b/src/ResManager.ts @@ -495,7 +495,8 @@ export class ResManager extends events.EventEmitter { /* gen jlink internal device list to file */ try { fs.unlinkSync(devXmlFile.path) } catch (error) { /* do nothing */ } - try { ChildProcess.execSync(cmd); } catch (error) { /* do nothing */ } + try { ChildProcess.execSync(cmd) } catch (error) { /* do nothing */ } + try { fs.unlinkSync(jlinkTmpCmdFile.path) } catch (error) { /* do nothing */ } // rm tmp file if (devXmlFile.IsFile()) { file = devXmlFile; } try { @@ -511,6 +512,11 @@ export class ResManager extends events.EventEmitter { const dom = parser.xml2js(file.Read()); + // rm tmp file + if (devXmlFile.IsFile()) { + try { fs.unlinkSync(devXmlFile.path) } catch (error) { } + } + if (dom.DeviceDatabase == undefined) { throw Error(`Not found 'DeviceDatabase' in devices xml, [file]: '${file.path}'`); } From c2b55d2796178865f665227c7e10202f29ed3c31 Mon Sep 17 00:00:00 2001 From: null Date: Sun, 21 Nov 2021 17:08:50 +0800 Subject: [PATCH 04/48] support modify project deps by yaml config file --- package.json | 13 +++++ src/EIDEProjectExplorer.ts | 115 ++++++++++++++++++++++++++++++++++--- src/EIDETypeDefine.ts | 4 ++ src/extension.ts | 1 + 4 files changed, 124 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index af69663d..0d45d626 100644 --- a/package.json +++ b/package.json @@ -464,6 +464,14 @@ "command": "_cl.eide.workspace.make.template", "title": "%eide.workspace.make.template%" }, + { + "command": "_cl.eide.project.modify.deps", + "title": "%eide.item.modify%", + "icon": { + "dark": "./res/icon/ConfigurationFile_16x.svg", + "light": "./res/icon/ConfigurationFile_16x.svg" + } + }, { "command": "_cl.eide.project.cppcheck.check_all", "title": "%eide.project.run.cppcheck%" @@ -1122,6 +1130,11 @@ "group": "inline", "when": "viewItem == SETTINGS_ITEM && view == Project" }, + { + "command": "_cl.eide.project.modify.deps", + "group": "inline", + "when": "viewItem == DEPENDENCE && view == Project" + }, { "command": "_cl.eide.project.addIncludeDir", "group": "inline", diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index 48571e3b..6ebda349 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -75,9 +75,8 @@ import { VirtualDocument } from './VirtualDocsProvider'; import { ResInstaller } from './ResInstaller'; import { ExeCmd, ExecutableOption, ExeFile } from '../lib/node-utility/Executable'; import { CmdLineHandler } from './CmdLineHandler'; -import * as CmsisConfigParser from './CmsisConfigParser' -import * as ini from 'ini'; import { WebPanelManager } from './WebPanelManager'; +import * as yml from 'yaml' enum TreeItemType { SOLUTION, @@ -1927,10 +1926,6 @@ export class ProjectExplorer { this._buildLock = true; - vscode.window.visibleTextEditors.forEach(editor => { - editor.document.save(); - }); - // save project before build prj.Save(); @@ -1966,9 +1961,6 @@ export class ProjectExplorer { return; } - /* save all editor */ - vscode.window.visibleTextEditors.forEach(editor => { editor.document.save(); }); - const cmdList: BuildCommandInfo[] = []; this.dataProvider.foreachProject((project, index) => { @@ -3244,6 +3236,111 @@ export class ProjectExplorer { } } + async ModifyCustomDependence(item: ProjTreeItem) { + + const prj = this.dataProvider.GetProjectByIndex(item.val.projectIndex); + const cusDep = prj.GetConfiguration().CustomDep_getDependence(); + + // gen deps yaml content + const yamlLines: string[] = [ + `#`, + `# You can modify the config by edit this file and save it.`, + `#`, + `` + ]; + + // push include path + yamlLines.push( + ``, + `# Header Include Path`, + `IncludeFolders:`, + `# - ./Your/Include/Folder/Path` + ); + cusDep.incList.forEach((path) => { + yamlLines.push(` - ${prj.ToRelativePath(path) || path}`) + }); + + // push lib folder path + yamlLines.push( + ``, + `# Library Search Path`, + `LibraryFolders:`, + `# - ./Your/Library/Path` + ); + cusDep.libList.forEach((path) => { + yamlLines.push(` - ${prj.ToRelativePath(path) || path}`) + }); + + // push macros + yamlLines.push( + ``, + `# Global Macro Defines`, + `Defines:`, + `# - TEST=1` + ); + cusDep.defineList.forEach((macro) => { + yamlLines.push(` - ${macro}`) + }); + + // write and open file + const yamlStr = yamlLines.join(os.EOL); + const tmpFile = File.fromArray([os.tmpdir(), `eide-deps-${Date.now()}.yaml`]); + tmpFile.Write(yamlStr); + + // reg cb, if file saved, apply modify + vscode.workspace.onDidSaveTextDocument((doc) => { + + // skip irrelevant files + if (NodePath.basename(doc.fileName) != tmpFile.name) return; + + // save to config + try { + const cfg = yml.parse(doc.getText()); + + // inc list + if (Array.isArray(cfg.IncludeFolders)) { + cusDep.incList = cfg.IncludeFolders + .filter((path: any) => typeof (path) == 'string') + .map((path: string) => prj.ToAbsolutePath(path)); + } + + // lib list + if (Array.isArray(cfg.LibraryFolders)) { + cusDep.libList = cfg.LibraryFolders + .filter((path: any) => typeof (path) == 'string') + .map((path: string) => prj.ToAbsolutePath(path)); + } + + // macro list + if (Array.isArray(cfg.Defines)) { + cusDep.defineList = cfg.Defines + .filter((path: any) => typeof (path) == 'string'); + } + + prj.GetConfiguration().CustomDep_NotifyChanged(); + } catch (error) { + GlobalEvent.emit('msg', ExceptionToMessage(error, 'Warning')); + } + }); + + // reg cb, if file closed, rm it + vscode.workspace.onDidCloseTextDocument((doc) => { + + // skip irrelevant files + if (NodePath.basename(doc.fileName) != tmpFile.name) return; + + // do + try { + fs.unlinkSync(tmpFile.path) + } catch (error) { + // do nothing + } + }); + + // open file + vscode.window.showTextDocument(vscode.Uri.parse(tmpFile.ToUri()), { preview: true }); + } + RemoveDependenceItem(item: ProjTreeItem) { const prj = this.dataProvider.GetProjectByIndex(item.val.projectIndex); switch ((item.val.obj).type) { diff --git a/src/EIDETypeDefine.ts b/src/EIDETypeDefine.ts index 407276e4..221e0b1d 100644 --- a/src/EIDETypeDefine.ts +++ b/src/EIDETypeDefine.ts @@ -1026,6 +1026,10 @@ export class ProjectConfiguration return this.config.dependenceList[index].depList[depIndex]; } + CustomDep_NotifyChanged() { + this.emit('dataChanged', { type: 'dependence' }); + } + CustomDep_RemoveInvalidIncDirs() { const dep = this.CustomDep_getDependence(); dep.incList = dep.incList.filter((_path) => { return new File(_path).IsDir(); }); diff --git a/src/extension.ts b/src/extension.ts index bc323642..f03d88b4 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -156,6 +156,7 @@ export async function activate(context: vscode.ExtensionContext) { subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.modifyOtherSettings', (item) => projectExplorer.ModifyOtherSettings(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.modify.deps', (item) => projectExplorer.ModifyCustomDependence(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.removeDependenceItem', (item) => projectExplorer.RemoveDependenceItem(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.importDependenceFromPack', (item) => projectExplorer.ImportPackageDependence(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.removeDependenceFromPack', (item) => projectExplorer.RemovePackageDependence(item))); From 8d148c2ad35c451565251e485dd65106c49f6f33 Mon Sep 17 00:00:00 2001 From: null Date: Sun, 21 Nov 2021 17:25:53 +0800 Subject: [PATCH 05/48] update changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a989dfa..80c468b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ *** +### [v2.14.1 RC1] +- 新增:向**项目依赖**视图增加一个**修改**按钮,允许以直接修改 yaml 配置文件的形式修改项目依赖 +- 修复:CMSIS Config Wizard 在解析不符合要求的字符串类型时,出现误判 +- 修复:删除 CMSIS 包之后,相应的 MCU 预定义宏被删除 +- 优化:读取完 JLink Device 列表后,删除临时文件 +- 优化:调整构建工具的 Log 显示 +*** + ### [v2.14.0] - 优化:增加一些编译器预定义宏 - 优化:优化 Builder Config UI,修复选项卡阴影区域显示不正常的问题 From 37d63a3a271d45ba42ad5439c4ebe01adb0b5bc2 Mon Sep 17 00:00:00 2001 From: null Date: Sun, 21 Nov 2021 17:35:24 +0800 Subject: [PATCH 06/48] optimize code --- src/EIDEProjectExplorer.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index 6ebda349..d263e572 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -3245,8 +3245,7 @@ export class ProjectExplorer { const yamlLines: string[] = [ `#`, `# You can modify the config by edit this file and save it.`, - `#`, - `` + `#` ]; // push include path From 8b66fcc6ec06fe0283fc2ce9835c249c8b1102ff Mon Sep 17 00:00:00 2001 From: null Date: Sun, 21 Nov 2021 19:55:37 +0800 Subject: [PATCH 07/48] optimize code --- package.json | 2 +- src/EIDEProjectExplorer.ts | 202 ++++++++++++++++++++----------------- 2 files changed, 113 insertions(+), 91 deletions(-) diff --git a/package.json b/package.json index 0d45d626..38b8129b 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "description": "A singlechip development environment for 8051/STM8/Cortex-M/RISC-V", "version": "2.14.0", "engines": { - "vscode": "^1.38.0" + "vscode": "^1.60.0" }, "categories": [ "Programming Languages", diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index d263e572..4acf9f9e 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -1713,13 +1713,24 @@ export class ProjectExplorer { // create cppcheck output channel this.cppcheck_out = vscode.window.createOutputChannel('eide-cppcheck'); - // when file saved, clear diagnostic - /* vscode.workspace.onDidSaveTextDocument((document) => { - const uri = document.uri; - if (this.cppcheck_diag.has(uri)) { - this.cppcheck_diag.delete(uri); - } - }); */ + // register doc event + context.subscriptions.push(vscode.workspace.onDidSaveTextDocument((doc) => { + this.onCustomDepYamlSaved(doc) + })); + + context.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors((curEditors) => { + + const closedList: string[] = []; + + this.prjCusDepChangesMap.forEach((__, fileName) => { + const idx = curEditors.findIndex((doc) => NodePath.basename(doc.document.fileName) == fileName); + if (idx == -1) closedList.push(fileName); + }); + + closedList.forEach((tmpFile) => { + this.onCustomDepYamlClosed(tmpFile); + }); + })); this.on('request_open_project', (fsPath: string) => this.dataProvider.OpenProject(fsPath)); this.on('request_create_project', (option: CreateOptions) => this.dataProvider.CreateProject(option)); @@ -3236,6 +3247,65 @@ export class ProjectExplorer { } } + // callbk, if config file saved, apply the changes + private onCustomDepYamlSaved(doc: vscode.TextDocument) { + + const tmpFileName = NodePath.basename(doc.fileName); + const prj = this.prjCusDepChangesMap.get(tmpFileName); + + // skip irrelevant files + if (prj == undefined) return; + + // save to config + try { + + const cusDep = prj.GetConfiguration().CustomDep_getDependence(); + const cfg = yml.parse(doc.getText()); + + // inc list + if (Array.isArray(cfg.IncludeFolders)) { + cusDep.incList = cfg.IncludeFolders + .filter((path: any) => typeof (path) == 'string') + .map((path: string) => prj.ToAbsolutePath(path)); + } + + // lib list + if (Array.isArray(cfg.LibraryFolders)) { + cusDep.libList = cfg.LibraryFolders + .filter((path: any) => typeof (path) == 'string') + .map((path: string) => prj.ToAbsolutePath(path)); + } + + // macro list + if (Array.isArray(cfg.Defines)) { + cusDep.defineList = cfg.Defines + .filter((path: any) => typeof (path) == 'string'); + } + + prj.GetConfiguration().CustomDep_NotifyChanged(); + + } catch (error) { + GlobalEvent.emit('msg', ExceptionToMessage(error, 'Warning')); + } + } + + // callbk, if config file closed, rm tmp file + private onCustomDepYamlClosed(tmpFileName: string) { + + // skip irrelevant files + if (!this.prjCusDepChangesMap.has(tmpFileName)) return; + + // do + try { + this.prjCusDepChangesMap.delete(tmpFileName); // remove from mapper + fs.unlinkSync(`${os.tmpdir()}/${tmpFileName}`); + } catch (error) { + GlobalEvent.emit('msg', ExceptionToMessage(error, 'Hidden')); + } + } + + // KV: + private prjCusDepChangesMap: Map = new Map(); async ModifyCustomDependence(item: ProjTreeItem) { const prj = this.dataProvider.GetProjectByIndex(item.val.projectIndex); @@ -3248,96 +3318,48 @@ export class ProjectExplorer { `#` ]; - // push include path - yamlLines.push( - ``, - `# Header Include Path`, - `IncludeFolders:`, - `# - ./Your/Include/Folder/Path` - ); - cusDep.incList.forEach((path) => { - yamlLines.push(` - ${prj.ToRelativePath(path) || path}`) - }); + // fill data + { + // push include path + yamlLines.push( + ``, + `# Header Include Path`, + `IncludeFolders:`, + `# - ./Your/Include/Folder/Path` + ); + cusDep.incList.forEach((path) => { + yamlLines.push(` - ${prj.ToRelativePath(path) || path}`) + }); - // push lib folder path - yamlLines.push( - ``, - `# Library Search Path`, - `LibraryFolders:`, - `# - ./Your/Library/Path` - ); - cusDep.libList.forEach((path) => { - yamlLines.push(` - ${prj.ToRelativePath(path) || path}`) - }); + // push lib folder path + yamlLines.push( + ``, + `# Library Search Path`, + `LibraryFolders:`, + `# - ./Your/Library/Path` + ); + cusDep.libList.forEach((path) => { + yamlLines.push(` - ${prj.ToRelativePath(path) || path}`) + }); - // push macros - yamlLines.push( - ``, - `# Global Macro Defines`, - `Defines:`, - `# - TEST=1` - ); - cusDep.defineList.forEach((macro) => { - yamlLines.push(` - ${macro}`) - }); + // push macros + yamlLines.push( + ``, + `# Global Macro Defines`, + `Defines:`, + `# - TEST=1` + ); + cusDep.defineList.forEach((macro) => { + yamlLines.push(` - ${macro}`) + }); + } // write and open file const yamlStr = yamlLines.join(os.EOL); const tmpFile = File.fromArray([os.tmpdir(), `eide-deps-${Date.now()}.yaml`]); tmpFile.Write(yamlStr); - - // reg cb, if file saved, apply modify - vscode.workspace.onDidSaveTextDocument((doc) => { - - // skip irrelevant files - if (NodePath.basename(doc.fileName) != tmpFile.name) return; - - // save to config - try { - const cfg = yml.parse(doc.getText()); - - // inc list - if (Array.isArray(cfg.IncludeFolders)) { - cusDep.incList = cfg.IncludeFolders - .filter((path: any) => typeof (path) == 'string') - .map((path: string) => prj.ToAbsolutePath(path)); - } - - // lib list - if (Array.isArray(cfg.LibraryFolders)) { - cusDep.libList = cfg.LibraryFolders - .filter((path: any) => typeof (path) == 'string') - .map((path: string) => prj.ToAbsolutePath(path)); - } - - // macro list - if (Array.isArray(cfg.Defines)) { - cusDep.defineList = cfg.Defines - .filter((path: any) => typeof (path) == 'string'); - } - - prj.GetConfiguration().CustomDep_NotifyChanged(); - } catch (error) { - GlobalEvent.emit('msg', ExceptionToMessage(error, 'Warning')); - } - }); - - // reg cb, if file closed, rm it - vscode.workspace.onDidCloseTextDocument((doc) => { - - // skip irrelevant files - if (NodePath.basename(doc.fileName) != tmpFile.name) return; - - // do - try { - fs.unlinkSync(tmpFile.path) - } catch (error) { - // do nothing - } - }); - - // open file - vscode.window.showTextDocument(vscode.Uri.parse(tmpFile.ToUri()), { preview: true }); + this.prjCusDepChangesMap.set(tmpFile.name, prj); // add to mapper + vscode.window.showTextDocument(vscode.Uri.parse(tmpFile.ToUri()), { preview: false }); } RemoveDependenceItem(item: ProjTreeItem) { From beb62f9d497fac318940e7d4816a1d78001bdb8c Mon Sep 17 00:00:00 2001 From: null Date: Sun, 21 Nov 2021 20:16:12 +0800 Subject: [PATCH 08/48] change note header for 'eide-deps-*.yaml' --- src/EIDEProjectExplorer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index 4acf9f9e..ad889989 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -3314,7 +3314,7 @@ export class ProjectExplorer { // gen deps yaml content const yamlLines: string[] = [ `#`, - `# You can modify the config by edit this file and save it.`, + `# You can modify the configuration by editing and saving this file.`, `#` ]; From add4247be698979c35ea6aa89f53c37ff69c0389 Mon Sep 17 00:00:00 2001 From: null <2584456014@qq.com> Date: Mon, 22 Nov 2021 16:31:32 +0800 Subject: [PATCH 09/48] fix: when switching the active editor, the dep yml config file is deleted --- src/EIDEProjectExplorer.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index ad889989..50f16cd1 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -1718,9 +1718,10 @@ export class ProjectExplorer { this.onCustomDepYamlSaved(doc) })); - context.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors((curEditors) => { + context.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors((__) => { const closedList: string[] = []; + const curEditors = vscode.window.visibleTextEditors; this.prjCusDepChangesMap.forEach((__, fileName) => { const idx = curEditors.findIndex((doc) => NodePath.basename(doc.document.fileName) == fileName); From beda5d860c0ab27dd5d80721aadc23656c16df31 Mon Sep 17 00:00:00 2001 From: null <2584456014@qq.com> Date: Mon, 22 Nov 2021 16:33:03 +0800 Subject: [PATCH 10/48] Update EIDEProjectExplorer.ts --- src/EIDEProjectExplorer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index 50f16cd1..04da4ac7 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -1718,7 +1718,7 @@ export class ProjectExplorer { this.onCustomDepYamlSaved(doc) })); - context.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors((__) => { + context.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors(() => { const closedList: string[] = []; const curEditors = vscode.window.visibleTextEditors; From 14f338beab9c763a18ae2d8cefd0749cecd38ecd Mon Sep 17 00:00:00 2001 From: null Date: Mon, 22 Nov 2021 21:57:48 +0800 Subject: [PATCH 11/48] fix: when switching the active editor, the dep yml config file is deleted --- src/EIDEProjectExplorer.ts | 43 +++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index 04da4ac7..e0bd8660 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -1714,24 +1714,8 @@ export class ProjectExplorer { this.cppcheck_out = vscode.window.createOutputChannel('eide-cppcheck'); // register doc event - context.subscriptions.push(vscode.workspace.onDidSaveTextDocument((doc) => { - this.onCustomDepYamlSaved(doc) - })); - - context.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors(() => { - - const closedList: string[] = []; - const curEditors = vscode.window.visibleTextEditors; - - this.prjCusDepChangesMap.forEach((__, fileName) => { - const idx = curEditors.findIndex((doc) => NodePath.basename(doc.document.fileName) == fileName); - if (idx == -1) closedList.push(fileName); - }); - - closedList.forEach((tmpFile) => { - this.onCustomDepYamlClosed(tmpFile); - }); - })); + context.subscriptions.push(vscode.workspace.onDidSaveTextDocument((doc) => this.onCustomDepYamlSaved(doc))); + context.subscriptions.push(vscode.workspace.onDidCloseTextDocument((doc) => this.onCustomDepYamlClosed(doc))); this.on('request_open_project', (fsPath: string) => this.dataProvider.OpenProject(fsPath)); this.on('request_create_project', (option: CreateOptions) => this.dataProvider.CreateProject(option)); @@ -3291,9 +3275,10 @@ export class ProjectExplorer { } // callbk, if config file closed, rm tmp file - private onCustomDepYamlClosed(tmpFileName: string) { + private onCustomDepYamlClosed(doc: vscode.TextDocument) { // skip irrelevant files + const tmpFileName = NodePath.basename(doc.fileName); if (!this.prjCusDepChangesMap.has(tmpFileName)) return; // do @@ -3355,11 +3340,27 @@ export class ProjectExplorer { }); } + const getTmpPathByProject = (prj: AbstractProject) => { + for (const KV of this.prjCusDepChangesMap) { + if (KV[1].getWsPath().toLowerCase() == prj.getWsPath().toLowerCase()) { + return KV[0]; + } + } + }; + // write and open file const yamlStr = yamlLines.join(os.EOL); - const tmpFile = File.fromArray([os.tmpdir(), `eide-deps-${Date.now()}.yaml`]); + const oldName = getTmpPathByProject(prj); + let tmpFile: File; + + if (oldName) { + tmpFile = File.fromArray([os.tmpdir(), oldName]); + } else {// if file not exist, add to mapper + tmpFile = File.fromArray([os.tmpdir(), `eide-deps-${Date.now()}.yaml`]); + this.prjCusDepChangesMap.set(tmpFile.name, prj); + } + tmpFile.Write(yamlStr); - this.prjCusDepChangesMap.set(tmpFile.name, prj); // add to mapper vscode.window.showTextDocument(vscode.Uri.parse(tmpFile.ToUri()), { preview: false }); } From 2bbf9d41d6e8edd40e0ea788dede524797a988ce Mon Sep 17 00:00:00 2001 From: null <2584456014@qq.com> Date: Tue, 23 Nov 2021 09:08:58 +0800 Subject: [PATCH 12/48] When save dep config, delete duplication item --- src/EIDEProjectExplorer.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index e0bd8660..a32fcea5 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -3249,22 +3249,31 @@ export class ProjectExplorer { // inc list if (Array.isArray(cfg.IncludeFolders)) { - cusDep.incList = cfg.IncludeFolders + const li = cfg.IncludeFolders .filter((path: any) => typeof (path) == 'string') .map((path: string) => prj.ToAbsolutePath(path)); + cusDep.incList = ArrayDelRepetition(li); + } else { + cusDep.incList = []; } // lib list if (Array.isArray(cfg.LibraryFolders)) { - cusDep.libList = cfg.LibraryFolders + const li = cfg.LibraryFolders .filter((path: any) => typeof (path) == 'string') .map((path: string) => prj.ToAbsolutePath(path)); + cusDep.libList = ArrayDelRepetition(li); + } else { + cusDep.libList = []; } // macro list if (Array.isArray(cfg.Defines)) { - cusDep.defineList = cfg.Defines + const li = cfg.Defines .filter((path: any) => typeof (path) == 'string'); + cusDep.defineList = ArrayDelRepetition(li); + } else { + cusDep.defineList = []; } prj.GetConfiguration().CustomDep_NotifyChanged(); From a56bbf0ebfb544858741629c3ddbac66c9701fc4 Mon Sep 17 00:00:00 2001 From: null Date: Tue, 23 Nov 2021 23:06:13 +0800 Subject: [PATCH 13/48] change: support independent armcc compiler paths --- CHANGELOG.md | 1 + package.json | 12 ++++ package.nls.json | 2 + package.nls.zh-CN.json | 2 + src/CodeBuilder.ts | 3 +- src/EIDEProject.ts | 6 +- src/EIDEProjectExplorer.ts | 84 +++++++++++++------------ src/OperationExplorer.ts | 91 +++++++++++++++------------ src/SettingManager.ts | 124 +++++++++++++++++++++++++------------ src/StringTable.ts | 9 ++- src/ToolchainManager.ts | 25 ++++---- 11 files changed, 219 insertions(+), 140 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80c468b4..2bbf1542 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - 修复:删除 CMSIS 包之后,相应的 MCU 预定义宏被删除 - 优化:读取完 JLink Device 列表后,删除临时文件 - 优化:调整构建工具的 Log 显示 +- **更改:支持为 Armcc v5/v6 工具链单独设置编译器路径,同时保留旧的 MDK TOOLS.INI 设置方法** *** ### [v2.14.0] diff --git a/package.json b/package.json index 38b8129b..4ac6fad4 100644 --- a/package.json +++ b/package.json @@ -304,6 +304,18 @@ "markdownDescription": "gnu sdcc for stm8 installation path", "default": "${userRoot}/.eide/tools/stm8_gnu_sdcc" }, + "EIDE.ARM.ARMCC5.InstallDirectory": { + "type": "string", + "scope": "resource", + "markdownDescription": "%settings.arm.armcc5.install.folder%", + "default": "" + }, + "EIDE.ARM.ARMCC6.InstallDirectory": { + "type": "string", + "scope": "resource", + "markdownDescription": "%settings.arm.armcc6.install.folder%", + "default": "" + }, "EIDE.ARM.GCC.Prefix": { "type": "string", "scope": "resource", diff --git a/package.nls.json b/package.nls.json index ee54aa98..be2ef588 100644 --- a/package.nls.json +++ b/package.nls.json @@ -97,6 +97,8 @@ "settings.iar.stm8.install.folder": "IAR for STM8 install directory [`example: D:\\IAR`]", "settings.sdcc.install.folder": "SDCC install folder [`example: C:\\Program Files (x86)\\SDCC`]", + "settings.arm.armcc5.install.folder": "Armcc v5 toolchain install directory [`example: D:\\ac5`]", + "settings.arm.armcc6.install.folder": "Armcc v6 toolchain install directory [`example: D:\\ac6`]", "settings.arm.gcc.install.folder": "GCC for ARM toolchain install directory [`example: D:\\arm-gcc\\8 2019-q3-update`]", "settings.arm.gcc.prefix": "ARM GCC toolchain prefix [`example: arm-none-eabi-`]", diff --git a/package.nls.zh-CN.json b/package.nls.zh-CN.json index a271761a..7b17e43d 100644 --- a/package.nls.zh-CN.json +++ b/package.nls.zh-CN.json @@ -96,6 +96,8 @@ "settings.iar.stm8.install.folder": "IAR for STM8 安装目录 [`example: D:\\IAR`]", "settings.sdcc.install.folder": "SDCC 安装目录 [`example: C:\\Program Files (x86)\\SDCC`]", + "settings.arm.armcc5.install.folder": "Armcc v5 toolchain 安装目录 [`example: D:\\ac5`]", + "settings.arm.armcc6.install.folder": "Armcc v6 toolchain 安装目录 [`example: D:\\ac6`]", "settings.arm.gcc.install.folder": "GNU Arm Embedded Toolchain 安装目录 [`example: D:\\arm-gcc\\8 2019-q3-update`]", "settings.arm.gcc.prefix": "GNU Arm Embedded Toolchain 编译器前缀 [`example: arm-none-eabi-`]", diff --git a/src/CodeBuilder.ts b/src/CodeBuilder.ts index eccc5631..ce72e249 100644 --- a/src/CodeBuilder.ts +++ b/src/CodeBuilder.ts @@ -805,8 +805,7 @@ class ARMCodeBuilder extends CodeBuilder { // convert elf if (['AC5', 'AC6'].includes(config.toolchain) && settingManager.IsConvertAxf2Elf()) { - const toolFolderName = config.toolchain === 'AC6' ? 'ARMCLANG' : 'ARMCC'; - const tool_root_folder = `${toolchain.getToolchainDir().path}\\${toolFolderName}`; + const tool_root_folder = toolchain.getToolchainDir().path; const ouput_path = `\${outDir}\\${config.name}`; const axf2elf_log = `\${outDir}\\axf2elf.log`; diff --git a/src/EIDEProject.ts b/src/EIDEProject.ts index 4bffc686..c0599601 100644 --- a/src/EIDEProject.ts +++ b/src/EIDEProject.ts @@ -1290,9 +1290,9 @@ export abstract class AbstractProject { if (!envFile.IsFile()) { const defTxt: string[] = [ - `###############################################################################################`, - `# project environment config, can be used for 'builder options', 'custom download command'`, - `###############################################################################################`, + `##################################################################################`, + `# project environment config, can be used for 'builder', 'downloader' ...`, + `##################################################################################`, ``, `# mcu ram size`, `#MCU_RAM_SIZE=0x00`, diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index a32fcea5..c5937e57 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -1310,51 +1310,53 @@ class ProjectDataProvider implements vscode.TreeDataProvider { const incs: string[] = this.importCmsisHeaders(baseInfo.rootFolder).map((f) => f.path); /* try resolve all deps */ - const mdkRoot = SettingManager.GetInstance().GetMdkDir(); - const fileTypes: string[] = ['source', 'header']; - rte_deps.forEach((dep) => { - /* check dep whether is valid */ - if (fileTypes.includes(dep.category || '') && dep.class && dep.packPath) { - const srcFileLi: File[] = []; - const vFolder = getVirtualFolder(`${VirtualSource.rootName}/::${dep.class}`, true); - - /* add all candidate files */ - if (dep.instance) { srcFileLi.push(new File(dep.instance[0])) } - srcFileLi.push(File.fromArray([mdkRoot.path, 'PACK', dep.packPath, dep.path])); - - /* resolve dependences */ - for (const srcFile of srcFileLi) { - - /* check condition */ - if (!srcFile.IsFile()) { continue; } - if (dep.category == 'source' && !vFolder) { continue; } - - let srcRePath: string | undefined = baseInfo.rootFolder.ToRelativePath(srcFile.path, false); - - /* if it's not in workspace, copy it */ - if (srcRePath == undefined) { - srcRePath = ['.cmsis', dep.packPath, dep.path].join(File.sep); - const realFolder = File.fromArray([baseInfo.rootFolder.path, NodePath.dirname(srcRePath)]); - realFolder.CreateDir(true); - realFolder.CopyFile(srcFile); - } + const mdkRoot = SettingManager.GetInstance().GetMdkArmDir(); + if (mdkRoot) { // MDK ARM dir, like: 'D:\keil\ARM' + const fileTypes: string[] = ['source', 'header']; + rte_deps.forEach((dep) => { + /* check dep whether is valid */ + if (fileTypes.includes(dep.category || '') && dep.class && dep.packPath) { + const srcFileLi: File[] = []; + const vFolder = getVirtualFolder(`${VirtualSource.rootName}/::${dep.class}`, true); + + /* add all candidate files */ + if (dep.instance) { srcFileLi.push(new File(dep.instance[0])) } + srcFileLi.push(File.fromArray([mdkRoot.path, 'PACK', dep.packPath, dep.path])); + + /* resolve dependences */ + for (const srcFile of srcFileLi) { + + /* check condition */ + if (!srcFile.IsFile()) { continue; } + if (dep.category == 'source' && !vFolder) { continue; } + + let srcRePath: string | undefined = baseInfo.rootFolder.ToRelativePath(srcFile.path, false); + + /* if it's not in workspace, copy it */ + if (srcRePath == undefined) { + srcRePath = ['.cmsis', dep.packPath, dep.path].join(File.sep); + const realFolder = File.fromArray([baseInfo.rootFolder.path, NodePath.dirname(srcRePath)]); + realFolder.CreateDir(true); + realFolder.CopyFile(srcFile); + } - /* if it's a source, add to project */ - if (dep.category == 'source' && vFolder) { - vFolder.files.push({ path: srcRePath }); - } + /* if it's a source, add to project */ + if (dep.category == 'source' && vFolder) { + vFolder.files.push({ path: srcRePath }); + } - /* if it's a header, add to include path */ - else if (dep.category == 'header') { - incs.push(`${baseInfo.rootFolder.path}${File.sep}${NodePath.dirname(srcRePath)}`); - } + /* if it's a header, add to include path */ + else if (dep.category == 'header') { + incs.push(`${baseInfo.rootFolder.path}${File.sep}${NodePath.dirname(srcRePath)}`); + } - return; /* resolved !, exit */ + return; /* resolved !, exit */ + } } - } - /* resolve failed !, store dep */ - unresolved_deps.push(dep); - }); + /* resolve failed !, store dep */ + unresolved_deps.push(dep); + }); + } /* add include paths for targets */ const mdk_rte_folder = File.fromArray([`${keilPrjFile.dir}`, 'RTE']); diff --git a/src/OperationExplorer.ts b/src/OperationExplorer.ts index de751971..4ffc7188 100644 --- a/src/OperationExplorer.ts +++ b/src/OperationExplorer.ts @@ -37,7 +37,12 @@ import { view_str$operation$create_from_internal_temp, view_str$operation$empty_8bit_prj, view_str$operation$empty_cortex_prj, - import_project_hit, view_str$import_project, view_str$operation$import_sel_out_folder, view_str$operation$empty_riscv_prj, view_str$operation$create_from_remote_repo, view_str$operation$create_from_local_disk, view_str$operation$create_empty_project_detail, view_str$operation$create_from_internal_temp_detail, view_str$operation$create_from_local_disk_detail, view_str$operation$create_from_remote_repo_detail, view_str$operation$openSettings, view_str$prompt$select_file, view_str$prompt$select_folder, view_str$prompt$select_tool_install_mode, view_str$prompt$tool_install_mode_online, view_str$prompt$tool_install_mode_local + import_project_hit, view_str$import_project, view_str$operation$import_sel_out_folder, view_str$operation$empty_riscv_prj, + view_str$operation$create_from_remote_repo, view_str$operation$create_from_local_disk, view_str$operation$create_empty_project_detail, + view_str$operation$create_from_internal_temp_detail, view_str$operation$create_from_local_disk_detail, + view_str$operation$create_from_remote_repo_detail, view_str$operation$openSettings, + view_str$prompt$select_file, view_str$prompt$select_folder, view_str$prompt$select_file_or_folder, view_str$prompt$select_tool_install_mode, + view_str$prompt$tool_install_mode_online, view_str$prompt$tool_install_mode_local } from './StringTable'; import { CreateOptions, ImportOptions, ProjectType } from './EIDETypeDefine'; import { File } from '../lib/node-utility/File'; @@ -560,11 +565,23 @@ export class OperationExplorer { detail: view_str$operation$setKeil51Path }, { - label: 'ARMCC', + label: 'MDK', type: 'AC5', - description: this.getStatusTxt(toolchainManager.isToolchainPathReady('AC5')), + description: this.getStatusTxt(settingManager.isMDKIniReady()), detail: view_str$operation$setMDKPath }, + { + label: 'ARMCC V5', + type: 'AC5', + description: this.getStatusTxt(toolchainManager.isToolchainPathReady('AC5')), + detail: view_str$operation$setToolchainInstallDir.replace('${name}', 'ARMCC V5 Toolchain') + }, + { + label: 'ARMCC V6', + type: 'AC6', + description: this.getStatusTxt(toolchainManager.isToolchainPathReady('AC6')), + detail: view_str$operation$setToolchainInstallDir.replace('${name}', 'ARMCC V6 Toolchain') + }, { label: 'GNU Arm Embedded Toolchain', type: 'GCC', @@ -640,27 +657,23 @@ export class OperationExplorer { let dialogOption: vscode.OpenDialogOptions; - switch (item.type) { - case 'AC5': - case 'Keil_C51': - dialogOption = { - openLabel: view_str$prompt$select_file, - filters: { - "TOOLS.INI file": ['INI'] - }, - canSelectFiles: true, - canSelectFolders: false, - canSelectMany: false - }; - break; - default: - dialogOption = { - openLabel: view_str$prompt$select_folder, - canSelectFiles: false, - canSelectFolders: true, - canSelectMany: false - }; - break; + if (item.type == 'Keil_C51' || item.label == 'MDK') { + dialogOption = { + openLabel: view_str$prompt$select_file, + filters: { + "TOOLS.INI file": ['INI'] + }, + canSelectFiles: true, + canSelectFolders: false, + canSelectMany: false + }; + } else { + dialogOption = { + openLabel: view_str$prompt$select_folder, + canSelectFiles: false, + canSelectFolders: true, + canSelectMany: false + }; } const path = await vscode.window.showOpenDialog(dialogOption); @@ -670,21 +683,21 @@ export class OperationExplorer { const tcManager = ToolchainManager.getInstance(); - switch (item.type) { - case 'AC5': - settingManager.SetARMINIPath(path[0].fsPath); - break; - case 'Keil_C51': - settingManager.SetC51INIPath(path[0].fsPath); - break; - default: - const iToolchian = tcManager.getToolchainByName(item.type); - if (iToolchian) { - vscode.workspace.getConfiguration().update( - iToolchian.settingName, path[0].fsPath, vscode.ConfigurationTarget.Global - ); - } - break; + if (item.type == 'Keil_C51') { + settingManager.SetC51INIPath(path[0].fsPath); + } + + else if (item.label == 'MDK') { + settingManager.SetMdkINIPath(path[0].fsPath); + } + + else { + const iToolchian = tcManager.getToolchainByName(item.type); + if (iToolchian) { + vscode.workspace.getConfiguration().update( + iToolchian.settingName, path[0].fsPath, vscode.ConfigurationTarget.Global + ); + } } } diff --git a/src/SettingManager.ts b/src/SettingManager.ts index dddea1ba..212ba750 100644 --- a/src/SettingManager.ts +++ b/src/SettingManager.ts @@ -51,7 +51,7 @@ export interface PortSerialOption { let _instance: SettingManager | undefined; -export interface INIStatus { +interface INIStatus { [name: string]: boolean; } @@ -69,7 +69,7 @@ export class SettingManager { private eideEnv: Map; private _checkStatus: INIStatus = { - 'ARM': false, + 'MDK': false, 'C51': false }; @@ -267,8 +267,12 @@ export class SettingManager { return this.getConfiguration().get('Option.UseTaskToBuild') || false; } - getINIStatus(): INIStatus { - return JSON.parse(JSON.stringify(this._checkStatus)); + isKeilC51IniReady(): boolean { + return this._checkStatus['C51']; + } + + isMDKIniReady(): boolean { + return this._checkStatus['MDK']; } isInsertCommandsAtBegin(): boolean { @@ -391,61 +395,99 @@ export class SettingManager { return new File(this.getGccFolderFromConfig('ARM.GCC.InstallDirectory', execName) || 'null'); } - SetARMINIPath(path: string) { + // --- + + getArmcc5Dir(): File { + return new File( + this.getGccFolderFromConfig('ARM.ARMCC5.InstallDirectory', 'armcc') || + this.pathCache.get('ARMCC5') || + 'null' + ); + } + + getArmcc6Dir(): File { + return new File( + this.getGccFolderFromConfig('ARM.ARMCC6.InstallDirectory', 'armclang') || + this.pathCache.get('ARMCC6') || + 'null' + ); + } + + SetMdkINIPath(path: string) { this.setConfigValue('ARM.INI.Path', path); } - private GetARMINIFile(): File { + private GetMdkINIFile(): File { const iniPath = this.getConfiguration().get('ARM.INI.Path') || ''; return new File(Utility.formatPath(iniPath)); } - GetMdkDir(): File { - return new File(this.pathCache.get('MDK') || 'null'); + GetMdkArmDir(): File | undefined { + const path = this.pathCache.get('MDK'); + if (path) { + return new File(path); + } } private refreshMDKStatus(): void { - /* parse from env */ - if (process.env && process.env['Keil_Root']) { - const rootFolder = Utility.formatPath(process.env['Keil_Root']); - const armFolder = File.fromArray([rootFolder, 'ARM']); - if (armFolder.IsDir() && - File.fromArray([armFolder.path, 'ARMCC']).IsDir()) { - this.pathCache.set('MDK', armFolder.path); - this._checkStatus['ARM'] = true; - return; /* found it, exit */ - } - } - /* parse from ini file */ - const iniFile = this.GetARMINIFile(); + const iniFile = this.GetMdkINIFile(); if (iniFile.IsFile()) { try { const iniData = ini.parse(iniFile.Read()); // check ini file fields if (iniData["ARM"] && iniData["ARM"]["PATH"]) { - const binDir = new File(formatPath((iniData["ARM"]["PATH"]).replace(/"/g, ''))); - // update and check - this.pathCache.set('MDK', binDir.path); - const cDir = File.fromArray([binDir.path, 'ARMCC']); - if (!cDir.IsDir()) { throw new Error('Not found folder, [path]: ' + cDir.path); } - this._checkStatus['ARM'] = true; + + // mdk ARM dir + const mdkArmDir = new File(formatPath((iniData["ARM"]["PATH"]).replace(/"/g, ''))); + + // cache arm dir + if (mdkArmDir.IsDir()) { + this.pathCache.set('MDK', mdkArmDir.path); + } + + // cache armcc5 path + const armcc5Dir = File.fromArray([mdkArmDir.path, 'ARMCC', 'bin']); + if (!armcc5Dir.IsDir()) { throw new Error('Not found folder, [path]: ' + armcc5Dir.path); } + this.pathCache.set('ARMCC5', armcc5Dir.dir); + + // update status + this._checkStatus['MDK'] = true; + + // cache armcc6 path + const armcc6Dir = File.fromArray([mdkArmDir.path, 'ARMCLANG', 'bin']); + if (armcc6Dir.IsDir()) { this.pathCache.set('ARMCC6', armcc6Dir.dir);; } + return; // mdk path is valid, return it } // invalid ini file else { - this.pathCache.delete('MDK'); + this.pathCache.delete('ARMCC5'); + this.pathCache.delete('ARMCC6'); throw new Error('Invalid ARM INI file, [path] : ' + iniFile.path); } + } catch (error) { GlobalEvent.emit('globalLog', ExceptionToMessage(error, 'Hidden')); } } - this._checkStatus['ARM'] = false; + /* parse from env */ + if (process.env && process.env['Keil_Root']) { + const rootFolder = Utility.formatPath(process.env['Keil_Root']); + const armFolder = File.fromArray([rootFolder, 'ARM']); + if (armFolder.IsDir() && + File.fromArray([armFolder.path, 'ARMCC']).IsDir()) { + this.pathCache.set('MDK', armFolder.path); + this._checkStatus['MDK'] = true; + return; /* found it, exit */ + } + } + + this._checkStatus['MDK'] = false; } //------------------------------- SDCC -------------------------------- @@ -486,18 +528,6 @@ export class SettingManager { private refreshC51Status(): void { - /* parse from env */ - if (process.env && process.env['Keil_Root']) { - const rootFolder = Utility.formatPath(process.env['Keil_Root']); - const c51Folder = File.fromArray([rootFolder, 'C51']); - if (c51Folder.IsDir() && - File.fromArray([c51Folder.path, 'BIN']).IsDir()) { - this.pathCache.set('C51', c51Folder.path); - this._checkStatus['C51'] = true; - return; /* found it, exit */ - } - } - /* parse from ini file */ const iniFile = this.GetC51INIFile(); if (iniFile.IsFile()) { @@ -525,6 +555,18 @@ export class SettingManager { } } + /* parse from env */ + if (process.env && process.env['Keil_Root']) { + const rootFolder = Utility.formatPath(process.env['Keil_Root']); + const c51Folder = File.fromArray([rootFolder, 'C51']); + if (c51Folder.IsDir() && + File.fromArray([c51Folder.path, 'BIN']).IsDir()) { + this.pathCache.set('C51', c51Folder.path); + this._checkStatus['C51'] = true; + return; /* found it, exit */ + } + } + this._checkStatus['C51'] = false; } } \ No newline at end of file diff --git a/src/StringTable.ts b/src/StringTable.ts index bf3fb072..936a3c1c 100644 --- a/src/StringTable.ts +++ b/src/StringTable.ts @@ -426,6 +426,11 @@ export const view_str$prompt$select_folder = [ `Select This Folder` ][langIndex]; +export const view_str$prompt$select_file_or_folder = [ + `选择该文件或文件夹`, + `Select This File Or Folder` +][langIndex]; + export const view_str$prompt$not_found_compiler = [ `无法找到编译器 '{}' 的安装位置 !`, `Not found the compiler '{}' installation location !` @@ -667,8 +672,8 @@ export const view_str$operation$setKeil51Path = [ ][langIndex]; export const view_str$operation$setMDKPath = [ - '设置 ARMCC 工具链的 TOOLS.INI 路径', - 'Set ARMCC Toolchain\'s \'TOOLS.INI\' path' + '设置 MDK 的 TOOLS.INI 路径', + 'Set MDK\'s \'TOOLS.INI\' path' ][langIndex]; export const view_str$operation$setToolchainInstallDir = [ diff --git a/src/ToolchainManager.ts b/src/ToolchainManager.ts index 4c62064d..4d145320 100644 --- a/src/ToolchainManager.ts +++ b/src/ToolchainManager.ts @@ -323,10 +323,11 @@ export class ToolchainManager { switch (name) { case 'AC5': + return File.fromArray([settingManager.getArmcc5Dir().path, 'bin']).IsDir(); case 'AC6': - return settingManager.getINIStatus()['ARM']; + return File.fromArray([settingManager.getArmcc6Dir().path, 'bin']).IsDir(); case 'Keil_C51': - return settingManager.getINIStatus()['C51']; + return settingManager.isKeilC51IniReady(); case 'GCC': return File.fromArray([settingManager.getGCCDir().path, 'bin']).IsDir(); case 'IAR_STM8': @@ -910,7 +911,7 @@ class AC5 implements IToolchian { readonly version = 4; - readonly settingName: string = 'EIDE.ARM.INI.Path'; + readonly settingName: string = 'EIDE.ARM.ARMCC5.InstallDirectory'; readonly categoryName: string = 'ARMCC'; @@ -934,7 +935,7 @@ class AC5 implements IToolchian { } getToolchainDir(): File { - return SettingManager.GetInstance().GetMdkDir(); + return SettingManager.GetInstance().getArmcc5Dir(); } getForceIncludeHeaders(): string[] { @@ -952,7 +953,7 @@ class AC5 implements IToolchian { } getSystemIncludeList(builderOpts: ICompileOptions): string[] { - const incDir = new File(this.getToolchainDir().path + File.sep + 'ARMCC' + File.sep + 'include'); + const incDir = File.fromArray([this.getToolchainDir().path, 'include']); if (incDir.IsDir()) { return [incDir].concat(incDir.GetList(File.EMPTY_FILTER)).map((f) => { return f.path; }); } @@ -964,7 +965,7 @@ class AC5 implements IToolchian { } getLibDirs(): string[] { - return [File.fromArray([this.getToolchainDir().path, 'ARMCC', 'lib']).path]; + return [File.fromArray([this.getToolchainDir().path, 'lib']).path]; } getDefaultConfig(): ICompileOptions { @@ -995,7 +996,7 @@ class AC6 implements IToolchian { readonly version = 3; - readonly settingName: string = 'EIDE.ARM.INI.Path'; + readonly settingName: string = 'EIDE.ARM.ARMCC6.InstallDirectory'; readonly categoryName: string = 'ARMCC'; @@ -1010,7 +1011,7 @@ class AC6 implements IToolchian { private readonly defMacroList: string[]; constructor() { - const armClang = File.fromArray([this.getToolchainDir().path, 'ARMCLANG', 'bin', 'armclang.exe']); + const armClang = File.fromArray([this.getToolchainDir().path, 'bin', 'armclang.exe']); this.defMacroList = this.getMacroList(armClang.path); } @@ -1060,7 +1061,7 @@ class AC6 implements IToolchian { } getToolchainDir(): File { - return SettingManager.GetInstance().GetMdkDir(); + return SettingManager.GetInstance().getArmcc6Dir(); } getInternalDefines(builderOpts: ICompileOptions): string[] { @@ -1073,8 +1074,8 @@ class AC6 implements IToolchian { getSystemIncludeList(builderOpts: ICompileOptions): string[] { return [ - File.fromArray([this.getToolchainDir().path, 'ARMCLANG', 'include']).path, - File.fromArray([this.getToolchainDir().path, 'ARMCLANG', 'include', 'libcxx']).path + File.fromArray([this.getToolchainDir().path, 'include']).path, + File.fromArray([this.getToolchainDir().path, 'include', 'libcxx']).path ]; } @@ -1089,7 +1090,7 @@ class AC6 implements IToolchian { } getLibDirs(): string[] { - return [File.fromArray([this.getToolchainDir().path, 'ARMCLANG', 'lib']).path]; + return [File.fromArray([this.getToolchainDir().path, 'lib']).path]; } getDefaultConfig(): ICompileOptions { From fb5cc4eb77f97acdced77a446d7df40733c5e941 Mon Sep 17 00:00:00 2001 From: null Date: Tue, 23 Nov 2021 23:16:53 +0800 Subject: [PATCH 14/48] change some hint string --- src/StringTable.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/StringTable.ts b/src/StringTable.ts index 936a3c1c..c24007b5 100644 --- a/src/StringTable.ts +++ b/src/StringTable.ts @@ -667,8 +667,8 @@ export const view_str$operation$baudrate = [ ][langIndex]; export const view_str$operation$setKeil51Path = [ - '设置 Keil_C51 工具链的 TOOLS.INI 路径', - 'Set Keil_C51 toolchain\'s \'TOOLS.INI\' path' + '设置 Keil_C51 的 TOOLS.INI 路径', + 'Set Keil_C51\'s \'TOOLS.INI\' path' ][langIndex]; export const view_str$operation$setMDKPath = [ From fbe6bf2cdc46b0593fb7aee5ae7a2209f32c4377 Mon Sep 17 00:00:00 2001 From: null <2584456014@qq.com> Date: Wed, 24 Nov 2021 08:52:33 +0800 Subject: [PATCH 15/48] Update arm.v5.verify.json --- lang/arm.v5.verify.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lang/arm.v5.verify.json b/lang/arm.v5.verify.json index 233c8d01..eaddd649 100644 --- a/lang/arm.v5.verify.json +++ b/lang/arm.v5.verify.json @@ -163,7 +163,7 @@ }, "optimize-for-time": { "markdownDescription": "Optimize for time", - "description.zh-cn": "代码时间优化", + "description.zh-cn": "Optimize for time", "type": "boolean", "enum": [ true, @@ -233,7 +233,7 @@ }, "strict-ANSI-C": { "markdownDescription": "strict ANSI C", - "description.zh-cn": "使用标准(严格)的 ANSI C", + "description.zh-cn": "strict ANSI C", "type": "boolean", "enum": [ true, @@ -430,4 +430,4 @@ } } } -} \ No newline at end of file +} From 7dbddcee4a971660d0d282a27131313729c95a51 Mon Sep 17 00:00:00 2001 From: null Date: Wed, 24 Nov 2021 23:08:40 +0800 Subject: [PATCH 16/48] add version number for binaries --- res/data/config.yaml | 5 +++++ src/ResManager.ts | 21 +++++++-------------- src/extension.ts | 14 +++++++++++--- 3 files changed, 23 insertions(+), 17 deletions(-) create mode 100644 res/data/config.yaml diff --git a/res/data/config.yaml b/res/data/config.yaml new file mode 100644 index 00000000..3a3d35ca --- /dev/null +++ b/res/data/config.yaml @@ -0,0 +1,5 @@ +# eide config + +version: '1.0' + +binaray_version: '2.14.1' diff --git a/src/ResManager.ts b/src/ResManager.ts index 17b2b54a..665deb4a 100644 --- a/src/ResManager.ts +++ b/src/ResManager.ts @@ -40,6 +40,7 @@ import { AbstractProject } from "./EIDEProject"; import { SettingManager } from "./SettingManager"; import * as utility from './utility' import { CmdLineHandler } from "./CmdLineHandler"; +import * as yaml from 'yaml'; let resManager: ResManager | undefined; @@ -90,7 +91,6 @@ export class ResManager extends events.EventEmitter { private cacheInfoList: FileCacheInfo[]; private stm8DevList: string[]; - private appConfigFile: File; private appConfig: any; private constructor(context?: vscode.ExtensionContext) { @@ -110,7 +110,6 @@ export class ResManager extends events.EventEmitter { } this.LoadSysEnv(); - this.appConfigFile = File.fromArray([this.GetAppDataDir().path, 'config.json']); this.InitIcons(); this.LoadAppConfig(); @@ -124,7 +123,6 @@ export class ResManager extends events.EventEmitter { GlobalEvent.on('extension_close', () => { this.saveCache(); - this.saveAppConfig(); }); } @@ -226,12 +224,14 @@ export class ResManager extends events.EventEmitter { //==================== private LoadAppConfig() { - if (this.appConfigFile.IsFile()) { + + const cfgFile = File.fromArray([this.GetAppDataDir().path, 'config.yaml']); + + if (cfgFile.IsFile()) { try { - this.appConfig = JSON.parse(this.appConfigFile.Read()); + this.appConfig = yaml.parse(cfgFile.Read()); } catch (error) { - this.appConfig = Object.create(null); - console.error(error); + GlobalEvent.emit('msg', ExceptionToMessage(error, 'Hidden')); } } } @@ -240,13 +240,6 @@ export class ResManager extends events.EventEmitter { return this.appConfig; } - saveAppConfig(newConfig?: any) { - if (typeof newConfig === 'object') { - this.appConfig = newConfig; - } - this.appConfigFile.Write(JSON.stringify(this.appConfig, undefined, 4)); - } - //===================== getCache(name: string): FileCacheInfo | undefined { diff --git a/src/extension.ts b/src/extension.ts index f03d88b4..2dc859b3 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -245,9 +245,12 @@ async function onSelectSerialBaudrate() { async function checkAndInstallBinaries(constex: vscode.ExtensionContext, forceInstall?: boolean): Promise { + const eideCfg = ResManager.GetInstance().getAppConfig(); + const binVersion = eideCfg['binaray_version'] ? `-${eideCfg['binaray_version']}` : '' + const downloadSites: string[] = [ - `https://raw.githubusercontent.com/github0null/eide-resource/master/binaries/bin.zip`, - `https://raw-github.github0null.io/github0null/eide-resource/master/binaries/bin.zip` + `https://raw.githubusercontent.com/github0null/eide-resource/master/binaries/bin${binVersion}.zip`, + `https://raw-github.github0null.io/github0null/eide-resource/master/binaries/bin${binVersion}.zip` ]; /* random select the order of site */ @@ -271,7 +274,7 @@ async function checkAndInstallBinaries(constex: vscode.ExtensionContext, forceIn let installedDone = false; try { - const tmpFile = File.fromArray([os.tmpdir(), 'eide-binaries.zip']); + const tmpFile = File.fromArray([os.tmpdir(), `eide-binaries${binVersion}.zip`]); /* make dir */ binFolder.CreateDir(true); @@ -355,6 +358,11 @@ async function checkAndInstallBinaries(constex: vscode.ExtensionContext, forceIn }); } + /* del tmp file */ + if (tmpFile.IsFile()) { + try { fs.unlinkSync(tmpFile.path) } catch (error) { } + } + } catch (error) { GlobalEvent.emit('error', error); } From 9a9a9c81ba34b9a3cb96e18a6c8a96207878dd98 Mon Sep 17 00:00:00 2001 From: null Date: Fri, 26 Nov 2021 22:30:48 +0800 Subject: [PATCH 17/48] when open import warnings, save it to workspace --- src/EIDEProjectExplorer.ts | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index c5937e57..8a673470 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -1367,26 +1367,38 @@ class ProjectDataProvider implements vscode.TreeDataProvider { /* log unresolved deps */ if (unresolved_deps.length > 0) { + + const title = `!!! ${WARNING} !!!`; + const lines: string[] = [ - `!!! ${WARNING} !!!`, + `${title}`, view_str$prompt$unresolved_deps, view_str$prompt$prj_location.replace('{}', baseInfo.workspaceFile.path), '---' ]; + unresolved_deps.forEach((dep) => { - const nLine: string[] = []; + let locate = dep.packPath; - if (dep.instance) { locate = baseInfo.rootFolder.ToRelativePath(dep.instance[0], false) || dep.instance[0] } - nLine.push( + if (dep.instance) { + locate = baseInfo.rootFolder + .ToRelativePath(dep.instance[0], false) || dep.instance[0] + } + + const nLine: string[] = [ `FileName: '${dep.path}'`, `\tClass: '${dep.class}'`, `\tCategory: '${dep.category}'`, `\tLocation: '${locate}'`, - ); + ]; + lines.push(nLine.join(os.EOL)); }); + const cont = lines.join(`${os.EOL}${os.EOL}`); - const doc = await vscode.workspace.openTextDocument({ content: cont }); + const file = File.fromArray([baseInfo.rootFolder.path, `${title}.txt`]); + file.Write(cont); // write content to file + const doc = await vscode.workspace.openTextDocument(vscode.Uri.parse(file.ToUri())); vscode.window.showTextDocument(doc, { preview: false }); } } From eda4a6afa260e8f730f6af4e641f4415191cd5a6 Mon Sep 17 00:00:00 2001 From: null Date: Sat, 27 Nov 2021 18:34:09 +0800 Subject: [PATCH 18/48] allow add compiler options for file --- .gitignore | 3 + CHANGELOG.md | 5 +- package.json | 21 +++++- package.nls.json | 1 + package.nls.zh-CN.json | 1 + res/data/template.files.options.yml | 34 ++++++++++ src/CodeBuilder.ts | 102 ++++++++++++++++++++++++---- src/EIDEProject.ts | 41 ++++++++++- src/EIDEProjectExplorer.ts | 6 ++ src/EIDETypeDefine.ts | 2 +- src/extension.ts | 1 + 11 files changed, 200 insertions(+), 17 deletions(-) create mode 100644 res/data/template.files.options.yml diff --git a/.gitignore b/.gitignore index a8e7cc30..77af049d 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,6 @@ bin_bk # shell script *.sh + +# test +test diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bbf1542..9738d1fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,15 @@ *** -### [v2.14.1 RC1] +### [v2.15.0 RC1] - 新增:向**项目依赖**视图增加一个**修改**按钮,允许以直接修改 yaml 配置文件的形式修改项目依赖 +- 新增:支持为单个的文件或组增加编译选项,支持使用 glob 模式匹配源文件和组 +- 新增:生成 .mapView 文件,打开即可显示可视化的资源视图(仅支持ARM工程) - 修复:CMSIS Config Wizard 在解析不符合要求的字符串类型时,出现误判 - 修复:删除 CMSIS 包之后,相应的 MCU 预定义宏被删除 - 优化:读取完 JLink Device 列表后,删除临时文件 - 优化:调整构建工具的 Log 显示 +- 更改:生成 obj 时,根据相对路径将 obj 生成至相应的文件夹树中 - **更改:支持为 Armcc v5/v6 工具链单独设置编译器路径,同时保留旧的 MDK TOOLS.INI 设置方法** *** diff --git a/package.json b/package.json index 4ac6fad4..aec5c7a8 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "@types/ftp": "^0.3.31", "@types/iconv-lite": "0.0.1", "@types/ini": "^1.3.30", + "@types/micromatch": "^4.0.2", "@types/mocha": "^5.2.7", "@types/node": "^12.12.17", "@types/vscode": "^1.38.0", @@ -76,6 +77,7 @@ "iconv-lite": "^0.5.0", "ini": "^2.0.0", "jsonc": "^2.0.0", + "micromatch": "^4.0.4", "unzipper": "^0.10.11", "x2js": "3.4.1", "yaml": "^1.10.2" @@ -628,6 +630,14 @@ "light": "./res/icon/AddFolder_16x.svg" } }, + { + "command": "_cl.eide.project.modify.files.options", + "title": "%eide.project.modify.files.options%", + "icon": { + "dark": "./res/icon/ConfigurationFile_16x.svg", + "light": "./res/icon/ConfigurationFile_16x.svg" + } + }, { "command": "_cl.eide.project.removeSrcDir", "title": "%eide.explorer.root.remove.folder%", @@ -1107,6 +1117,15 @@ "command": "_cl.eide.project.addSrcDir", "when": "viewItem == PROJECT && view == Project" }, + { + "command": "_cl.eide.project.modify.files.options", + "group": "inline", + "when": "viewItem == PROJECT && view == Project" + }, + { + "command": "_cl.eide.project.modify.files.options", + "when": "viewItem == PROJECT && view == Project" + }, { "command": "_cl.eide.project.sourceRoot.refresh", "group": "inline", @@ -1328,4 +1347,4 @@ } ] } -} \ No newline at end of file +} diff --git a/package.nls.json b/package.nls.json index be2ef588..313c612f 100644 --- a/package.nls.json +++ b/package.nls.json @@ -25,6 +25,7 @@ "eide.project.clean": "Clean", "eide.project.upload": "Upload Program To Device", "eide.project.gen.makefile": "Generate Makefile Template", + "eide.project.modify.files.options": "Append Compiler Options For Files", "eide.workspace.build": "Build All", "eide.workspace.rebuild": "Rebuild All", diff --git a/package.nls.zh-CN.json b/package.nls.zh-CN.json index 7b17e43d..eb9d92d4 100644 --- a/package.nls.zh-CN.json +++ b/package.nls.zh-CN.json @@ -25,6 +25,7 @@ "eide.project.clean": "清理", "eide.project.upload": "烧录", "eide.project.gen.makefile": "生成 Makefile 模板", + "eide.project.modify.files.options": "向文件附加编译选项", "eide.workspace.build": "构建所有项目", "eide.workspace.rebuild": "重新构建所有项目", diff --git a/res/data/template.files.options.yml b/res/data/template.files.options.yml new file mode 100644 index 00000000..30d938f8 --- /dev/null +++ b/res/data/template.files.options.yml @@ -0,0 +1,34 @@ +######################################################################################### +# append compiler options for files or virtual folders +######################################################################################### + +version: '1.0' + +######################################################################################### +# rules +# +# syntax: +# : +# +# examples: +# main.cpp: --cpp11 -Og ... +# src/*.c: -gnu -O2 ... +# src/lib/**/*.cpp: --cpp11 -Os ... +# !Application/*.c: -O0 +# +# For more syntax, please refer to: https://www.npmjs.com/package/micromatch +# +######################################################################################### + +# +# for source files with filesystem paths +# +files: +# test/**/test.c: --c99 + +# +# for source files with virtual paths +# +virtualPathFiles: +# test/**/*.c: --c99 + diff --git a/src/CodeBuilder.ts b/src/CodeBuilder.ts index ce72e249..ea965309 100644 --- a/src/CodeBuilder.ts +++ b/src/CodeBuilder.ts @@ -22,6 +22,12 @@ SOFTWARE. */ +import * as fs from 'fs'; +import * as vscode from 'vscode'; +import * as NodePath from 'path'; +import * as events from 'events'; +import * as globmatch from 'micromatch' + import { AbstractProject } from "./EIDEProject"; import { ResManager } from "./ResManager"; import { File } from "../lib/node-utility/File"; @@ -35,9 +41,6 @@ import { GlobalEvent } from "./GlobalEvents"; import { ExceptionToMessage, newMessage } from "./Message"; import { CmdLineHandler } from "./CmdLineHandler"; -import * as fs from 'fs'; -import * as vscode from 'vscode'; -import * as NodePath from 'path'; import { ArrayDelRepetition } from "../lib/node-utility/Utility"; import { DependenceManager } from "./DependenceManager"; import { WorkspaceManager } from "./WorkspaceManager"; @@ -45,7 +48,6 @@ import { ToolchainName } from "./ToolchainManager"; import { md5, sha256 } from "./utility"; import { MakefileGen } from "./Makefile"; import { append2SysEnv } from "./Platform"; -import * as events from 'events'; import { FileWatcher } from "../lib/node-utility/FileWatcher"; export interface BuildOptions { @@ -68,6 +70,8 @@ export interface BuilderParams { ram?: number; rom?: number; sourceList: string[]; + sourceParams?: { [name: string]: string; }; + sourceParamsMtime?: number; incDirs: string[]; libDirs: string[]; defines: string[]; @@ -101,23 +105,96 @@ export abstract class CodeBuilder { this._event.emit(event, arg); } - getSourceList(): string[] { + genSourceInfo(prevBuilderParams: BuilderParams): { + sources: string[], + params?: { [name: string]: string; } + paramsModTime?: number; + } { - const srcList: string[] = []; + const srcList: { path: string, virtualPath?: string; }[] = []; + const srcParams: { [name: string]: string; } = {}; const fGoups = this.project.getFileGroups(); const filter = AbstractProject.getSourceFileFilter(); + // filter source files for (const group of fGoups) { if (group.disabled) continue; // skip disabled group for (const source of group.files) { if (source.disabled) continue; // skip disabled file if (!filter.some((reg) => reg.test(source.file.path))) continue; // skip non-source const rePath = this.project.ToRelativePath(source.file.path, false); - srcList.push(rePath || source.file.path); + const fInfo: any = { path: rePath || source.file.path } + if (AbstractProject.isVirtualSourceGroup(group)) { + fInfo.virtualPath = `${group.name}/${source.file.name}` + } + srcList.push(fInfo); } } - return srcList; + // append user options for files + try { + const options = this.project.getFilesOptions(); + + // parser + const matcher = (parttenInfo: any, fieldName: string) => { + srcList.forEach((srcInf: any) => { + if (!srcInf[fieldName]) return; // skip if not exist + for (const expr in parttenInfo) { + const path = (srcInf[fieldName]).replace(/\\/g, '/'); + if (globmatch.isMatch(path, expr)) { + if (srcParams[srcInf.path]) { + srcParams[srcInf.path] += ' ' + (parttenInfo[expr] || '') + } else { + srcParams[srcInf.path] = parttenInfo[expr] || ''; + } + } + } + }); + }; + + if (options) { + + // virtual folder files + if (typeof options?.virtualPathFiles == 'object') { + const parttenInfo = options?.virtualPathFiles; + matcher(parttenInfo, 'virtualPath'); + } + + // filesystem files + if (typeof options?.files == 'object') { + const parttenInfo = options?.files; + matcher(parttenInfo, 'path'); + } + + // if src options is modified to null but old is not null, + // we need make source recompile + const oldSrcParams = prevBuilderParams.sourceParams; + for (const path in oldSrcParams) { + if (srcParams[path] == undefined && oldSrcParams[path] != undefined && + oldSrcParams[path] != '') { + srcParams[path] = ""; // make it empty to trigger recompile + } + } + } + + } catch (err) { + GlobalEvent.emit('msg', ExceptionToMessage(err, 'Hidden')); + GlobalEvent.emit('msg', newMessage('Warning', `Append files options failed !, msg: ${err.message || ''}`)); + } + + let mTimeMs: number | undefined; + + try { + mTimeMs = fs.statSync(this.project.getFilesOptionsFile().path).mtimeMs + } catch (error) { + // do nothing + } + + return { + sources: srcList.map((inf) => inf.path), + params: srcParams, + paramsModTime: mTimeMs + } } getIncludeDirs(): string[] { @@ -270,6 +347,8 @@ export abstract class CodeBuilder { .compileConfigModel.getOptions(this.project.getEideDir().path, config); const memMaxSize = this.getMaxSize(); const modeList: string[] = []; + const prevParams: BuilderParams = File.IsFile(paramsPath) ? JSON.parse(fs.readFileSync(paramsPath, 'utf8')) : {}; + const sourceInfo = this.genSourceInfo(prevParams); const builderOptions: BuilderParams = { name: config.name, @@ -285,7 +364,9 @@ export abstract class CodeBuilder { rom: memMaxSize?.rom, incDirs: this.getIncludeDirs().map((incPath) => { return this.project.ToRelativePath(incPath, false) || incPath; }), libDirs: this.getLibDirs().map((libPath) => { return this.project.ToRelativePath(libPath, false) || libPath; }), - sourceList: this.getSourceList().sort(), + sourceList: sourceInfo.sources.sort(), + sourceParams: sourceInfo.params, + sourceParamsMtime: sourceInfo.paramsModTime, defines: this.getDefineList(), options: JSON.parse(JSON.stringify(compileOptions)), env: this.project.getProjectEnv() @@ -321,9 +402,6 @@ export abstract class CodeBuilder { // check whether need rebuild project if (this.isRebuild() == false) { try { - const prevParams: BuilderParams = - File.IsFile(paramsPath) ? JSON.parse(fs.readFileSync(paramsPath, 'utf8')) : {}; - // not found hash from old params file if (prevParams.sha == undefined) { this.enableRebuild(); diff --git a/src/EIDEProject.ts b/src/EIDEProject.ts index c0599601..015c7fb9 100644 --- a/src/EIDEProject.ts +++ b/src/EIDEProject.ts @@ -26,6 +26,9 @@ import * as fs from 'fs'; import * as vscode from 'vscode'; import * as NodePath from 'path'; import * as events from 'events'; +import * as ini from 'ini'; +import * as os from 'os'; +import * as yaml from 'yaml'; import { File } from '../lib/node-utility/File'; import { FileWatcher } from '../lib/node-utility/FileWatcher'; @@ -50,8 +53,6 @@ import { isNullOrUndefined } from 'util'; import { DeleteDir } from './Platform'; import { IDebugConfigGenerator } from './DebugConfigGenerator'; import { md5, copyObject } from './utility'; -import * as ini from 'ini'; -import * as os from 'os'; import { ResInstaller } from './ResInstaller'; import { view_str$prompt$not_found_compiler } from './StringTable'; import { SettingManager } from './SettingManager'; @@ -649,6 +650,12 @@ export interface BaseProjectInfo { prjConfig: ProjectConfiguration; } +export interface FilesOptions { + version: string; + files?: { [key: string]: string }; + virtualPathFiles?: { [key: string]: string }; +} + export type DataChangeType = 'pack' | 'dependence' | 'compiler' | 'uploader' | 'files'; export abstract class AbstractProject { @@ -721,6 +728,10 @@ export abstract class AbstractProject { return p1.getWsPath() === p2.getWsPath(); } + static isVirtualSourceGroup(grp: FileGroup): boolean { + return (grp).dir == undefined; + } + private loadProjectDirectory() { // load root folder @@ -1336,6 +1347,32 @@ export abstract class AbstractProject { } } + getFilesOptionsFile(): File { + + const target = this.getCurrentTarget().toLowerCase(); + const templateFile = File.fromArray([ + ResManager.GetInstance().GetAppDataDir().path, 'template.files.options.yml' + ]); + + const optFile = File.fromArray([this.getEideDir().path, `${target}.files.options.yml`]); + if (!optFile.IsFile()) { + optFile.Write(templateFile.Read()); + } + + return optFile; + } + + getFilesOptions(): FilesOptions | undefined { + + const optFile = this.getFilesOptionsFile(); + + try { + return yaml.parse(optFile.Read()); + } catch (error) { + GlobalEvent.emit('msg', newMessage('Warning', `error format '${optFile.name}', it must be a yaml file !`)); + } + } + //--- protected loadToolchain() { diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index 8a673470..b0b48f21 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -3246,6 +3246,12 @@ export class ProjectExplorer { } } + async showFilesOptions(item: ProjTreeItem) { + const prj = this.dataProvider.GetProjectByIndex(item.val.projectIndex); + const optFile = prj.getFilesOptionsFile(); + vscode.window.showTextDocument(vscode.Uri.parse(optFile.ToUri()), { preview: true }); + } + // callbk, if config file saved, apply the changes private onCustomDepYamlSaved(doc: vscode.TextDocument) { diff --git a/src/EIDETypeDefine.ts b/src/EIDETypeDefine.ts index 221e0b1d..9fdeabf3 100644 --- a/src/EIDETypeDefine.ts +++ b/src/EIDETypeDefine.ts @@ -83,7 +83,7 @@ export interface FileItem { } export interface FileGroup { - name: string; + name: string; // dir name if it's system folder, else it's a virtual path files: FileItem[]; disabled?: boolean; // for mdk group info } diff --git a/src/extension.ts b/src/extension.ts index 2dc859b3..f3840b4f 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -121,6 +121,7 @@ export async function activate(context: vscode.ExtensionContext) { subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.addSrcDir', (item) => projectExplorer.AddSrcDir(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.removeSrcDir', (item) => projectExplorer.RemoveSrcDir(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.sourceRoot.refresh', (item) => projectExplorer.refreshSrcRoot(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.modify.files.options', (item) => projectExplorer.showFilesOptions(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.filesystem_folder_add_file', (item) => projectExplorer.fs_folderAddFile(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.filesystem_folder_add', (item) => projectExplorer.fs_folderAdd(item))); From 1f8dad3b99bf1ed894c6baa33d3309432ed095df Mon Sep 17 00:00:00 2001 From: null Date: Sat, 27 Nov 2021 23:14:45 +0800 Subject: [PATCH 19/48] support display map view --- CHANGELOG.md | 5 +- package.json | 19 ++++- package.nls.json | 1 + package.nls.zh-CN.json | 1 + res/icon/file_type_map.svg | 1 + src/EIDEProject.ts | 9 +++ src/SettingManager.ts | 4 ++ src/extension.ts | 144 ++++++++++++++++++++++++++++++++++++- 8 files changed, 180 insertions(+), 4 deletions(-) create mode 100644 res/icon/file_type_map.svg diff --git a/CHANGELOG.md b/CHANGELOG.md index 9738d1fa..7bf26f35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,9 @@ ### [v2.15.0 RC1] - 新增:向**项目依赖**视图增加一个**修改**按钮,允许以直接修改 yaml 配置文件的形式修改项目依赖 -- 新增:支持为单个的文件或组增加编译选项,支持使用 glob 模式匹配源文件和组 -- 新增:生成 .mapView 文件,打开即可显示可视化的资源视图(仅支持ARM工程) +- 新增:向**项目资源**视图增加一个**配置**按钮,允许为单个的文件或组增加任意编译选项,支持使用 glob 模式匹配源文件和组 +- 新增:在输出目录生成 .map.view 文件,打开即可显示 RAM/FLASH 资源使用视图(仅支持ARM工程) +- 新增:支持在线下载和安装 Keil 芯片支持包 - 修复:CMSIS Config Wizard 在解析不符合要求的字符串类型时,出现误判 - 修复:删除 CMSIS 包之后,相应的 MCU 预定义宏被删除 - 优化:读取完 JLink Device 列表后,删除临时文件 diff --git a/package.json b/package.json index aec5c7a8..99b7035e 100644 --- a/package.json +++ b/package.json @@ -83,6 +83,17 @@ "yaml": "^1.10.2" }, "contributes": { + "customEditors": [ + { + "viewType": "cl.eide.map.view", + "displayName": "MapView", + "selector": [ + { + "filenamePattern": "*.map.view" + } + ] + } + ], "walkthroughs": [ { "id": "eide.startup.walkthroughs", @@ -132,6 +143,12 @@ { "title": "Embedded IDE", "properties": { + "EIDE.Option.MapViewParserDepth": { + "type": "integer", + "scope": "resource", + "markdownDescription": "%settings.option.mapView.parser.depth%", + "default": 5 + }, "EIDE.Option.ShowSourceReferences": { "type": "boolean", "scope": "resource", @@ -1347,4 +1364,4 @@ } ] } -} +} \ No newline at end of file diff --git a/package.nls.json b/package.nls.json index 313c612f..9912efd7 100644 --- a/package.nls.json +++ b/package.nls.json @@ -82,6 +82,7 @@ "settings.option.use.task.to.build": "Use Task to build project instead of Terminal", "settings.option.insert.extcommands.at.begin": "The built-in command lines will insert at the beginning of the `beforeBuildTasks / afterBuildTasks`", "settings.option.show.source.references": "Show c/c++ header references for source file", + "settings.option.mapView.parser.depth": "The depth limit of the obj file path when *.map.view is displayed. Obj files larger than this depth are ignored.", "settings.template.use.proxy": "Use github proxy to improve network speed (experimental function)", "settings.template.repo.url": "remote public github repository url, format: ``/``/contents/``", diff --git a/package.nls.zh-CN.json b/package.nls.zh-CN.json index eb9d92d4..d169463a 100644 --- a/package.nls.zh-CN.json +++ b/package.nls.zh-CN.json @@ -120,6 +120,7 @@ "settings.option.disable.editor_context.menu": "禁用编辑器上下文菜单", "settings.option.disable.explorer_context.menu": "禁用资源浏览器上下文菜单", "settings.option.show.source.references": "显示源文件的头文件引用", + "settings.option.mapView.parser.depth": "显示 *.map.view 时,obj 文件路径的深度限制。大于该深度的 obj 文件将被忽略", "string.eide.startup.walkthroughs": "Embedded IDE 演示", "string.eide.startup.walkthroughs.detail": "我们将向您展示如何开始使用 Embedded IDE 。", diff --git a/res/icon/file_type_map.svg b/res/icon/file_type_map.svg new file mode 100644 index 00000000..660b7649 --- /dev/null +++ b/res/icon/file_type_map.svg @@ -0,0 +1 @@ +file_type_map \ No newline at end of file diff --git a/src/EIDEProject.ts b/src/EIDEProject.ts index 015c7fb9..7aa5f6e4 100644 --- a/src/EIDEProject.ts +++ b/src/EIDEProject.ts @@ -1992,6 +1992,14 @@ class EIDEProject extends AbstractProject { settings['C_Cpp.default.cStandard'] = "c99"; } + if (settings['[yaml]'] === undefined) { + settings['[yaml]'] = { + "editor.insertSpaces": true, + "editor.tabSize": 4, + "editor.autoIndent": "advanced" + } + } + if (toolchain.name === 'Keil_C51') { if (settings['C_Cpp.errorSquiggles'] === undefined) { settings['C_Cpp.errorSquiggles'] = "Disabled"; @@ -2005,6 +2013,7 @@ class EIDEProject extends AbstractProject { "keroc.hex-fmt", "hars.cppsnippets", "zixuanwang.linkerscript", + "redhat.vscode-yaml" ]; const prjInfo = this.GetConfiguration().config; diff --git a/src/SettingManager.ts b/src/SettingManager.ts index 212ba750..b5d82b63 100644 --- a/src/SettingManager.ts +++ b/src/SettingManager.ts @@ -242,6 +242,10 @@ export class SettingManager { //--------------------- Global Option ------------------------ + getMapViewParserDepth(): number { + return this.getConfiguration().get('Option.MapViewParserDepth') || 1; + } + isDisplaySourceRefs(): boolean { return this.getConfiguration().get('Option.ShowSourceReferences') || false; } diff --git a/src/extension.ts b/src/extension.ts index f3840b4f..7eb4c8e6 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -27,6 +27,7 @@ import * as fs from 'fs'; import * as os from 'os'; import * as unzipper from 'unzipper'; import * as NodePath from 'path'; +import * as ChildProcess from 'child_process'; import { GlobalEvent } from './GlobalEvents'; import { OperationExplorer } from './OperationExplorer'; @@ -407,7 +408,7 @@ function exportEnvToSysPath() { async function InitComponents(context: vscode.ExtensionContext): Promise { - // init all modules + // init resource manager ResManager.GetInstance(context); /* check binaries, if not found, install it ! */ @@ -470,6 +471,13 @@ async function InitComponents(context: vscode.ExtensionContext): Promise { + + const viewFile = new File(document.fileName); + const title = viewFile.noSuffixName; + + // init + webviewPanel.title = title; + webviewPanel.iconPath = vscode.Uri.parse(ResManager.GetInstance().GetIconByName('file_type_map.svg').ToUri()); + webviewPanel.webview.html = this.genHtmlCont(title, 'No Content'); + webviewPanel.onDidDispose(() => { + if (this.fileWatcher) { + this.fileWatcher.Close(); + this.fileWatcher = undefined; + } + }); + + if (!viewFile.IsFile()) { + webviewPanel.webview.html = this.genHtmlCont(title, `Error: file '${viewFile.path}' is not a file !`); + return; + } + + const conf: { tool?: string, fileName?: string } = yaml.parse(viewFile.Read()); + const defName = viewFile.noSuffixName + '.map'; + const mapFile = File.fromArray([viewFile.dir, conf.fileName || defName]); + + if (!mapFile.IsFile()) { + webviewPanel.webview.html = this.genHtmlCont(title, `Error: file '${mapFile.path}' is not a file !`); + return; + } + + if (!conf.tool) { + webviewPanel.webview.html = this.genHtmlCont(title, `Error: invalid toolchain type !`); + return; + } + + let toolName = 'ARM_MICRO'; + let fileDepth = SettingManager.GetInstance().getMapViewParserDepth(); + + if (fileDepth < 0) + fileDepth = 1; + + switch (conf.tool) { + case 'AC5': + case 'AC6': + toolName = 'ARM_MICRO'; + break; + case 'GCC': + toolName = 'GCC_ARM'; + break; + default: + webviewPanel.webview.html = this.genHtmlCont(title, `Error: we not support this toolchain type: '${conf.tool}' !`); + return; + } + + const showMapView = () => { + try { + const execPath = ResManager.GetInstance().getBuilderDir() + File.sep + 'memap'; + const lines = ChildProcess + .execSync(`${execPath} -t ${toolName} -d ${fileDepth} "${mapFile.path}"`) + .toString().split(/\r\n|\n/); + + // append color + for (let index = 0; index < lines.length; index++) { + const line = lines[index]; + lines[index] = line + .replace(/\((\+[^0]\d*)\)/g, `($1)`) + .replace(/\((\-[^0]\d*)\)/g, `($1)`) + .replace(/^(\s*\|\s*)(Subtotals)/, `$1$2`) + .replace(/^(\s*Total)/, `\n$1`); + } + + webviewPanel.webview.html = this.genHtmlCont(title, lines.join('\n')); + } catch (error) { + webviewPanel.webview.html = this.genHtmlCont(title, `Parse error: \r\n${error.message}`); + return; + } + }; + + if (this.fileWatcher == undefined) { + try { + this.fileWatcher = new FileWatcher(mapFile, false); + this.fileWatcher.OnChanged = () => showMapView(); + this.fileWatcher.Watch(); + } catch (error) { + this.fileWatcher?.Close(); + this.fileWatcher = undefined; + } + } + + showMapView(); + } + + private genHtmlCont(title: string, cont: string): string { + return ` + + + + + + ${title} + + + +
+
${cont}
+
+ + + `; + } +} + //----------------------------------------- const sfrMap: Map = new Map(); From bb1be4da627bd29a007035a59391153e229a5fbf Mon Sep 17 00:00:00 2001 From: null Date: Sun, 28 Nov 2021 14:14:38 +0800 Subject: [PATCH 20/48] new: support download cmsis pack from repo --- package.json | 12 +- package.nls.json | 5 +- package.nls.zh-CN.json | 5 +- src/EIDEProjectExplorer.ts | 227 +++++++++++++++++++++++++++++++------ src/OperationExplorer.ts | 2 +- src/ResManager.ts | 20 +--- src/SettingManager.ts | 9 +- src/utility.ts | 132 ++++++++++++++++++++- 8 files changed, 346 insertions(+), 66 deletions(-) diff --git a/package.json b/package.json index 99b7035e..bce6fa93 100644 --- a/package.json +++ b/package.json @@ -233,18 +233,24 @@ "markdownDescription": "%settings.option.insert.extcommands.at.begin%", "default": false }, - "EIDE.Template.Repository.UseProxy": { + "EIDE.Repository.UseProxy": { "type": "boolean", "scope": "machine", - "markdownDescription": "%settings.template.use.proxy%", + "markdownDescription": "%settings.repo.use.proxy%", "default": true }, - "EIDE.Template.Repository.Url": { + "EIDE.Repository.Template.Url": { "type": "string", "scope": "machine", "markdownDescription": "%settings.template.repo.url%", "default": "github0null/eide-resource/contents/eide-template-list" }, + "EIDE.Repository.CmsisPack.Url": { + "type": "string", + "scope": "machine", + "markdownDescription": "%settings.cmsispack.repo.url%", + "default": "github0null/eide-cmsis-pack/contents/packages" + }, "EIDE.SerialPortMonitor.DefaultPort": { "type": "string", "scope": "resource", diff --git a/package.nls.json b/package.nls.json index 9912efd7..51da2b21 100644 --- a/package.nls.json +++ b/package.nls.json @@ -84,8 +84,9 @@ "settings.option.show.source.references": "Show c/c++ header references for source file", "settings.option.mapView.parser.depth": "The depth limit of the obj file path when *.map.view is displayed. Obj files larger than this depth are ignored.", - "settings.template.use.proxy": "Use github proxy to improve network speed (experimental function)", - "settings.template.repo.url": "remote public github repository url, format: ``/``/contents/``", + "settings.repo.use.proxy": "Use proxy to improve network speed for github (experimental function)", + "settings.template.repo.url": "Public github template repository url, format: ``/``/contents/``", + "settings.cmsispack.repo.url": "Public github cmsis-pack repository url, format: ``/``/contents/``", "settings.serial.def.port": "Default port name", "settings.serial.show.toolbar": "Show serialport status bar", diff --git a/package.nls.zh-CN.json b/package.nls.zh-CN.json index d169463a..20418f1e 100644 --- a/package.nls.zh-CN.json +++ b/package.nls.zh-CN.json @@ -82,8 +82,9 @@ "settings.option.use.task.to.build": "使用 vscode 任务执行编译命令", "settings.option.insert.extcommands.at.begin": "内置的构建任务将被插入到 `beforeBuildTasks / afterBuildTasks` 之前", - "settings.template.use.proxy": "使用 github 代理加速模板下载", - "settings.template.repo.url": "远程 github 模板仓库地址, 格式: ``/``/contents/``", + "settings.repo.use.proxy": "使用代理加速 github 资源下载", + "settings.template.repo.url": "Github 模板仓库地址, 格式: ``/``/contents/``", + "settings.cmsispack.repo.url": "Github cmsis 包仓库地址, 格式: ``/``/contents/``", "settings.serial.def.port": "默认串口名称", "settings.serial.show.toolbar": "显示串口工具栏", diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index b0b48f21..36f5415e 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -68,7 +68,11 @@ import { HexUploaderManager, HexUploaderType } from './HexUploader'; import { Compress, CompressOption } from './Compress'; import { DependenceManager } from './DependenceManager'; import { ArrayDelRepetition } from '../lib/node-utility/Utility'; -import { copyObject, downloadFileWithProgress, getDownloadUrlFromGit, runShellCommand } from './utility'; +import { + copyObject, downloadFileWithProgress, getDownloadUrlFromGit, + runShellCommand, redirectHost, readGithubRepoFolder, FileCache, + genGithubHash +} from './utility'; import { append2SysEnv, DeleteDir, kill } from './Platform'; import { KeilARMOption, KeilC51Option, KeilParser, KeilRteDependence } from './KeilXmlParser'; import { VirtualDocument } from './VirtualDocsProvider'; @@ -77,6 +81,7 @@ import { ExeCmd, ExecutableOption, ExeFile } from '../lib/node-utility/Executabl import { CmdLineHandler } from './CmdLineHandler'; import { WebPanelManager } from './WebPanelManager'; import * as yml from 'yaml' +import { GitFileInfo } from './WebInterface/GithubInterface'; enum TreeItemType { SOLUTION, @@ -1549,33 +1554,6 @@ class ProjectDataProvider implements vscode.TreeDataProvider { } } - async InstallKeilPackage(prjIndex: number, reporter?: (progress?: number, message?: string) => void) { - - if (this.prjList[prjIndex].GetPackManager().GetPack()) { - GlobalEvent.emit('msg', { - type: 'Warning', - contentType: 'string', - content: 'You should uninstall old package before install a new one !' - }); - return; - } - - const packFile = await vscode.window.showOpenDialog({ - canSelectFolders: false, - canSelectFiles: true, - openLabel: install_this_pack, - filters: { - 'CMSIS Package': ['pack'] - } - }); - - if (packFile === undefined) { - return; - } - - return this.prjList[prjIndex].InstallPack(new File(packFile[0].fsPath), reporter); - } - async UninstallKeilPackage(item: ProjTreeItem) { const prj = this.prjList[item.val.projectIndex]; if (prj.GetPackManager().GetPack()) { @@ -1649,7 +1627,7 @@ class ProjectDataProvider implements vscode.TreeDataProvider { return { label: dev.name, description: dev.core }; }); const item = await vscode.window.showQuickPick(devList, { - placeHolder: 'found ' + devList.length + ' devices, ' + set_device_hint, + placeHolder: 'Found ' + devList.length + ' devices, ' + set_device_hint, canPickMany: false, matchOnDescription: true }); @@ -1779,7 +1757,7 @@ export class ProjectExplorer { private async createTarget(prj: AbstractProject) { let targetName = await vscode.window.showInputBox({ - placeHolder: 'input a target name', + placeHolder: 'Input a target name', validateInput: (val: string) => { if (val.length > 25) { return `string is too long !, length must < 25, current is ${val.length}`; } if (!/^[\w-]+$/.test(val)) { return `string can only contain word, number or '_' !`; } @@ -1800,7 +1778,7 @@ export class ProjectExplorer { private async deleteTarget(prj: AbstractProject) { - const selTarget = await vscode.window.showQuickPick(prj.getTargets(), { placeHolder: 'select a target to delete' }); + const selTarget = await vscode.window.showQuickPick(prj.getTargets(), { placeHolder: 'Select a target to delete' }); if (selTarget === undefined) { return; } const curTarget = prj.getCurrentTarget(); @@ -1900,7 +1878,7 @@ export class ProjectExplorer { vscode.window.showQuickPick(records.reverse(), { canPickMany: false, - placeHolder: `found ${records.length} results, select one to open`, + placeHolder: `Found ${records.length} results, select one to open`, matchOnDescription: false, matchOnDetail: true, ignoreFocusOut: false @@ -2111,30 +2089,205 @@ export class ProjectExplorer { return; } + if (prj.GetPackManager().GetPack()) { + GlobalEvent.emit('msg', { + type: 'Warning', + contentType: 'string', + content: 'You should uninstall old package before install a new one !' + }); + this.installLocked = false; + return; + } + vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, - title: `Installing CMSIS package` + title: `Installing cmsis package` }, (progress) => { - return new Promise(async (resolve) => { + return new Promise(async (resolve_) => { + + const resolve = () => { + this.installLocked = false; + resolve_(); + }; + try { progress.report({ message: 'preparing ...' }); - await this.dataProvider.InstallKeilPackage(prjIndex, (_progress, msg) => { + let packFile: File; + + const insType = await vscode.window.showQuickPick([ + { + label: 'From Repo', + detail: 'Download cmsis pack from the repository and install' + }, + { + label: 'From Disk', + detail: 'Select cmsis pack file from your computer and install' + } + ], { + placeHolder: `Select an installation type. Press 'Esc' to exit`, + canPickMany: false, + ignoreFocusOut: true + }); + + if (insType === undefined) { // canceled, exit + resolve(); + return; + } + + // download from internet + if (insType.label == 'From Repo') { + + progress.report({ message: 'waiting download task done ...' }); + + const res = await this.startDownloadCmsisPack(); + + if (res === undefined) { // canceled, exit + resolve(); + return; + } + + if (res instanceof Error) { + GlobalEvent.emit('msg', ExceptionToMessage(res, 'Warning')); + resolve(); + return; + } + + packFile = res; + } + + // from disk + else { + const urls = await vscode.window.showOpenDialog({ + canSelectFolders: false, + canSelectFiles: true, + openLabel: install_this_pack, + filters: { + 'Cmsis Package': ['pack'] + } + }); + + if (urls === undefined) { // canceled, exit + resolve(); + return; + } + + packFile = new File(urls[0].fsPath); + } + + await prj.InstallPack(packFile, (_progress, msg) => { progress.report({ increment: _progress ? 12 : undefined, message: msg }); }); + + resolve(); + } catch (error) { GlobalEvent.emit('msg', ExceptionToMessage(error, 'Warning')); + resolve(); } - this.installLocked = false; - resolve(); }); }); } + private async startDownloadCmsisPack(): Promise { + + const redirectUri = (uri: string) => { + return SettingManager.GetInstance().isUseGithubProxy() ? redirectHost(uri) : uri; + }; + + // URL: https://api.github.com/repos/github0null/eide-cmsis-pack/contents/packages + const repoUrl = redirectUri('api.github.com/repos/' + SettingManager.GetInstance().getCmsisPackRepositoryUrl()); + + return await vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + title: `Download cmsis package` + }, async (progress, cancelToken) => { + + progress.report({ message: `reading package list ...` }); + + const pkgList = await readGithubRepoFolder(repoUrl); + if (pkgList instanceof Error) { + return pkgList; + } + + progress.report({ message: `waiting cmsis package selection ...` }); + + const itemList: vscode.QuickPickItem[] = pkgList + .filter((inf) => inf.type == 'file') + .map((fileInfo) => { + return { + label: fileInfo.name, + detail: `Size: ${(fileInfo.size / 1000000).toFixed(1)} MB, Sha: ${fileInfo.sha}`, + val: fileInfo + }; + }); + + const item: any = await vscode.window.showQuickPick(itemList, { + placeHolder: `Found ${pkgList.length} packages, select one to install. Press 'Esc' to exit`, + canPickMany: false, + ignoreFocusOut: true, + matchOnDescription: true + }); + + if (item == undefined) { // user canceled + return undefined; + } + + try { + + const gitFileInfo: GitFileInfo = item.val; + let packageFile: File | undefined; + + const resManager = ResManager.GetInstance(); + const packDir = File.fromArray([resManager.getEideHomeFolder().path, 'pack', 'cmsis']); + packDir.CreateDir(true); + + // read cache + const cache = new FileCache(packDir); + packageFile = cache.get(gitFileInfo.name, gitFileInfo.sha); + if (packageFile) { // found cache, use it + return packageFile; + } + + // download it + progress.report({ message: `initializing download '${gitFileInfo.name}' ...` }); + + if (gitFileInfo.download_url == undefined) { + return new Error(`Can't download '${gitFileInfo.name}', not download url found !`); + } + + const url = redirectUri(gitFileInfo.download_url); + const buff = await downloadFileWithProgress(url, gitFileInfo.name, progress, cancelToken); + + if (buff == undefined) { // canceled + return undefined; + } + + if (buff instanceof Error) { + return buff; + } + + // save file + packageFile = File.fromArray([packDir.path, gitFileInfo.name]); + fs.writeFileSync(packageFile.path, buff); + + // add to cache + const sha = genGithubHash(buff); + cache.add(packageFile.name, sha); + cache.save(); + + return packageFile; + + } catch (error) { + return error; + } + }); + } + private exportLocked: boolean = false; async ExportToTemplate(prjItem?: ProjTreeItem, isWorkspace?: boolean) { diff --git a/src/OperationExplorer.ts b/src/OperationExplorer.ts index 4ffc7188..475d71da 100644 --- a/src/OperationExplorer.ts +++ b/src/OperationExplorer.ts @@ -825,7 +825,7 @@ export class OperationExplorer { const res = await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, - title: 'searching from ' + hostName + ' ...', + title: 'Searching from ' + hostName + ' ...', cancellable: true }, (_, token): Thenable> => { return new Promise(async (resolve) => { diff --git a/src/ResManager.ts b/src/ResManager.ts index 665deb4a..d148fb70 100644 --- a/src/ResManager.ts +++ b/src/ResManager.ts @@ -138,22 +138,6 @@ export class ResManager extends events.EventEmitter { return codePage; } - static getGithubHash(f: File | Buffer): string { - if (f instanceof File) { - const header = Buffer.from('blob ' + f.getSize() + '\0'); - const buf = Buffer.concat([header, fs.readFileSync(f.path)], header.length + f.getSize()); - const hash = crypto.createHash('sha1'); - hash.update(buf); - return hash.digest('hex'); - } else { - const header = Buffer.from('blob ' + f.length + '\0'); - const buf = Buffer.concat([header, f], header.length + f.length); - const hash = crypto.createHash('sha1'); - hash.update(buf); - return hash.digest('hex'); - } - } - static getAppFullName(): string { return appName; } @@ -325,6 +309,10 @@ export class ResManager extends events.EventEmitter { } } + getEideHomeFolder(): File { + return File.fromArray([os.homedir(), '.eide']); + } + GetLogDir(): File { const logDir = this.GetDir('log'); if (logDir === undefined) { diff --git a/src/SettingManager.ts b/src/SettingManager.ts index b5d82b63..8ecd1bfd 100644 --- a/src/SettingManager.ts +++ b/src/SettingManager.ts @@ -259,12 +259,17 @@ export class SettingManager { } getGithubRepositoryUrl(): string { - return (this.getConfiguration().get('Template.Repository.Url') || 'null') + return (this.getConfiguration().get('Repository.Template.Url') || 'null') + .trim().replace(/^https:\/\//i, ''); + } + + getCmsisPackRepositoryUrl(): string { + return (this.getConfiguration().get('Repository.CmsisPack.Url') || 'null') .trim().replace(/^https:\/\//i, ''); } isUseGithubProxy(): boolean { - return this.getConfiguration().get('Template.Repository.UseProxy') || false; + return this.getConfiguration().get('Repository.UseProxy') || false; } isUseTaskToBuild(): boolean { diff --git a/src/utility.ts b/src/utility.ts index 590b04e3..51859375 100644 --- a/src/utility.ts +++ b/src/utility.ts @@ -25,15 +25,16 @@ import * as vscode from 'vscode'; import * as crypto from 'crypto'; import * as child_process from 'child_process'; +import * as fs from 'fs'; import { WorkspaceManager } from "./WorkspaceManager"; import { CmdLineHandler } from "./CmdLineHandler"; -import { GlobalEvent } from "./GlobalEvents"; import { ExceptionToMessage } from "./Message"; import { NetRequest, NetResponse } from '../lib/node-utility/NetRequest'; import { File } from '../lib/node-utility/File'; +import { GitFileInfo } from './WebInterface/GithubInterface'; -export function runShellCommand(title: string, commandLine: string, cmdPath?: string, env?: any) { +export function runShellCommand(title: string, commandLine: string, cmdPath?: string, env?: any): Error | undefined { try { if (WorkspaceManager.getInstance().hasWorkspaces()) { // use task @@ -54,7 +55,7 @@ export function runShellCommand(title: string, commandLine: string, cmdPath?: st terminal.sendText(CmdLineHandler.DeleteCmdPrefix(commandLine)); } } catch (error) { - GlobalEvent.emit('msg', ExceptionToMessage(error, 'Warning')); + return error; } } @@ -249,3 +250,128 @@ export async function getDownloadUrlFromGit(repo: string, folder: string, fileNa resolve(fInfo); }); } + +export async function readGithubRepoFolder(remoteUrl_: string, token?: vscode.CancellationToken): Promise { + + // URL: https://api.github.com/repos/github0null/eide-doc/contents/eide-template-list + const remoteUrl = remoteUrl_.replace(/^http[s]?:\/\//, ''); + const netReq = new NetRequest(); + + let reqError: Error | undefined; + netReq.on('error', (err) => { + (err).message = `Failed to connect '${remoteUrl}'`; + reqError = err; + }); + + const pathArr = (remoteUrl).split('/'); + const hostName = pathArr[0]; + const path = '/' + pathArr.slice(1).join('/'); + + token?.onCancellationRequested(() => { + netReq.emit('abort'); + }); + + const res = await netReq.Request({ + host: hostName, + path: path, + timeout: 3000, + headers: { 'User-Agent': 'Mozilla/5.0' } + }, 'https'); + + if (!res.success) { + const errMsg = res.msg ? `, msg: ${res.msg}` : ''; + return new Error(`Can't connect to github repository !${errMsg}`); + } else if (res.content === undefined) { + const errMsg = res.msg ? `, msg: ${res.msg}` : ''; + return new Error(`Can't get content from github repository !${errMsg}`); + } + + if (reqError) { + return reqError; + } + + return res.content; +} + +export function genGithubHash(f: File | Buffer): string { + if (f instanceof File) { + const header = Buffer.from('blob ' + f.getSize() + '\0'); + const buf = Buffer.concat([header, fs.readFileSync(f.path)], header.length + f.getSize()); + const hash = crypto.createHash('sha1'); + hash.update(buf); + return hash.digest('hex'); + } else { + const header = Buffer.from('blob ' + f.length + '\0'); + const buf = Buffer.concat([header, f], header.length + f.length); + const hash = crypto.createHash('sha1'); + hash.update(buf); + return hash.digest('hex'); + } +} + +interface FileCacheInfo { + + version: string; + + files: { name: string; sha: string; }[]; +} + +export class FileCache { + + private folder: File; + private cacheFile: File; + private cache: FileCacheInfo; + + public constructor(rootFolder: File) { + this.folder = rootFolder; + this.cacheFile = File.fromArray([rootFolder.path, 'cache.json']); + this.cache = this.cacheFile.IsFile() ? JSON.parse(this.cacheFile.Read()) : { version: '1.0', files: [] }; + } + + public add(name: string, sha: string) { + + const idx = this.cache.files.findIndex((inf) => inf.name == name); + + if (idx != -1) { + this.cache.files[idx].sha = sha; + } else { + this.cache.files.push({ + name: name, + sha: sha + }); + } + } + + public get(name: string, sha: string): File | undefined { + + const idx = this.cache.files.findIndex((inf) => { + return inf.name == name && inf.sha == sha; + }); + + if (idx == -1) { + return undefined; + } + + const f = File.fromArray([this.folder.path, this.cache.files[idx].name]); + if (!f.IsFile()) { + return undefined; + } + + return f; + } + + public clear(name?: string) { + if (name) { + const idx = this.cache.files.findIndex((inf) => inf.name == name); + if (idx != -1) { + this.cache.files.splice(idx, 1); + } + } else { + this.cache.files = []; + } + } + + public save() { + this.cacheFile.Write(JSON.stringify(this.cache)); + } +} From 3b254e3204d510fa7ef6da6118189390a3c7b080 Mon Sep 17 00:00:00 2001 From: null Date: Sun, 28 Nov 2021 14:33:20 +0800 Subject: [PATCH 21/48] random select proxy host --- src/utility.ts | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/utility.ts b/src/utility.ts index 51859375..7c9c8b75 100644 --- a/src/utility.ts +++ b/src/utility.ts @@ -111,12 +111,28 @@ export const toolsUrlMap = { }; const hostMap: any = { - 'api.github.com': 'api-github.em-ide.com', - 'raw.githubusercontent.com': 'raw-github.em-ide.com' + 'api.github.com': [ + 'api-github.em-ide.com' + ], + 'raw.githubusercontent.com': [ + 'raw-github.em-ide.com', + 'raw-github.github0null.io' + ] }; export function redirectHost(url: string) { - for (const host in hostMap) { url = url.replace(host, hostMap[host]); } + + // replace host + for (const host in hostMap) { + const hostList = hostMap[host]; + if (hostList.length > 1) { + const idx = Math.floor(Math.random() * hostList.length); // random index + url = url.replace(host, hostList[idx]); + } else { + url = url.replace(host, hostList[0]); + } + } + return url; } From 83d1a003263b1d8ef6c4f4e35124ef6511084fea Mon Sep 17 00:00:00 2001 From: null Date: Sun, 28 Nov 2021 16:06:13 +0800 Subject: [PATCH 22/48] update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bf26f35..097ca102 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ - 新增:向**项目依赖**视图增加一个**修改**按钮,允许以直接修改 yaml 配置文件的形式修改项目依赖 - 新增:向**项目资源**视图增加一个**配置**按钮,允许为单个的文件或组增加任意编译选项,支持使用 glob 模式匹配源文件和组 - 新增:在输出目录生成 .map.view 文件,打开即可显示 RAM/FLASH 资源使用视图(仅支持ARM工程) -- 新增:支持在线下载和安装 Keil 芯片支持包 +- 新增:支持在线下载安装 Keil 芯片支持包,默认远程仓库地址:https://github.com/github0null/eide-cmsis-pack - 修复:CMSIS Config Wizard 在解析不符合要求的字符串类型时,出现误判 - 修复:删除 CMSIS 包之后,相应的 MCU 预定义宏被删除 - 优化:读取完 JLink Device 列表后,删除临时文件 From df339a9a8892e569b0390003fa69284ac27d1137 Mon Sep 17 00:00:00 2001 From: null Date: Sun, 28 Nov 2021 18:50:21 +0800 Subject: [PATCH 23/48] optimize ram/flash layout view --- res/html/StorageLayoutView/index.html | 44 +++++++++++++++++++++------ 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/res/html/StorageLayoutView/index.html b/res/html/StorageLayoutView/index.html index 72b0a242..846583e9 100644 --- a/res/html/StorageLayoutView/index.html +++ b/res/html/StorageLayoutView/index.html @@ -31,13 +31,35 @@ list-style-type: none; } - #submit { + #header { + position: -webkit-sticky; /* Safari */ + position: sticky; + padding: 12px; + top: 0px; + z-index: 10; + background-color: var(--vscode-editor-background); + } + + #header-cont { display: flex; - justify-content: center; + align-items: center; + justify-content: space-between; + } + + #button-cont { + display: flex; + justify-items: center; + justify-content: flex-end; + } + + h3 { + margin: 10px 4px; + color: var(--vscode-editor-foreground) !important; } button { margin: 4px; + margin-left: 8px; } .form-group { @@ -266,6 +288,15 @@ + - -
- - -
From f00c282f285e4e9c118f2944d05328810acdaf60 Mon Sep 17 00:00:00 2001 From: null Date: Sun, 28 Nov 2021 19:29:50 +0800 Subject: [PATCH 24/48] gen builder params with indent --- src/CodeBuilder.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/CodeBuilder.ts b/src/CodeBuilder.ts index ea965309..5c1c534a 100644 --- a/src/CodeBuilder.ts +++ b/src/CodeBuilder.ts @@ -441,11 +441,7 @@ export abstract class CodeBuilder { } // write project build params - if (this.useShowParamsMode) { - fs.writeFileSync(paramsPath, JSON.stringify(builderOptions, undefined, 4)); - } else { - fs.writeFileSync(paramsPath, JSON.stringify(builderOptions)); - } + fs.writeFileSync(paramsPath, JSON.stringify(builderOptions, undefined, 4)); // generate makefile params if (settingManager.isGenerateMakefileParams()) { From 1bd7a215b060b08758df843a0ec04213c4159184 Mon Sep 17 00:00:00 2001 From: null Date: Sun, 28 Nov 2021 22:41:34 +0800 Subject: [PATCH 25/48] modify: don't parse internal macros from ac6 compiler --- src/ToolchainManager.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ToolchainManager.ts b/src/ToolchainManager.ts index 4d145320..e0379c2c 100644 --- a/src/ToolchainManager.ts +++ b/src/ToolchainManager.ts @@ -1008,6 +1008,7 @@ class AC6 implements IToolchian { readonly verifyFileName: string = 'arm.v6.verify.json'; + /* private readonly defMacroList: string[]; constructor() { @@ -1038,6 +1039,7 @@ class AC6 implements IToolchian { return ['__GNUC__=4', '__GNUC_MINOR__=2', '__GNUC_PATCHLEVEL__=1']; } } + */ newInstance(): IToolchian { return new AC6(); @@ -1065,7 +1067,7 @@ class AC6 implements IToolchian { } getInternalDefines(builderOpts: ICompileOptions): string[] { - return this.defMacroList; + return []; } getCustomDefines(): string[] | undefined { From 50e41a5a7a24eabb63301b8c32474c37fde173a7 Mon Sep 17 00:00:00 2001 From: github0null <2584456014@qq.com> Date: Mon, 29 Nov 2021 14:45:29 +0800 Subject: [PATCH 26/48] optimize map viewer --- CHANGELOG.md | 2 +- src/extension.ts | 177 +++++++++++++++++++++++++++++++---------------- 2 files changed, 120 insertions(+), 59 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 097ca102..e4538049 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ ### [v2.15.0 RC1] - 新增:向**项目依赖**视图增加一个**修改**按钮,允许以直接修改 yaml 配置文件的形式修改项目依赖 - 新增:向**项目资源**视图增加一个**配置**按钮,允许为单个的文件或组增加任意编译选项,支持使用 glob 模式匹配源文件和组 -- 新增:在输出目录生成 .map.view 文件,打开即可显示 RAM/FLASH 资源使用视图(仅支持ARM工程) +- 新增:在输出目录生成 .map.view 文件,打开即可显示 RAM/FLASH 资源使用视图(仅支持ARM和GCC工程) - 新增:支持在线下载安装 Keil 芯片支持包,默认远程仓库地址:https://github.com/github0null/eide-cmsis-pack - 修复:CMSIS Config Wizard 在解析不符合要求的字符串类型时,出现误判 - 修复:删除 CMSIS 包之后,相应的 MCU 预定义宏被删除 diff --git a/src/extension.ts b/src/extension.ts index 7eb4c8e6..093a2ae1 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,25 +1,25 @@ /* - MIT License - - Copyright (c) 2019 github0null - - 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. + MIT License + + Copyright (c) 2019 github0null + + 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. */ import * as vscode from 'vscode'; @@ -527,9 +527,29 @@ function RegisterGlobalEvent() { import * as yaml from 'yaml' import { FileWatcher } from '../lib/node-utility/FileWatcher'; +interface MapViewRef { + + webview: vscode.Webview; + + title: string; + + toolName: string; + + treeDepth: number; + + mapPath: string; +}; + +interface MapViewInfo { + + watcher: FileWatcher; + + refList: MapViewRef[]; +}; + class MapViewEditorProvider implements vscode.CustomTextEditorProvider { - private fileWatcher: FileWatcher | undefined; + private mapViews: Map = new Map(); resolveCustomTextEditor(document: vscode.TextDocument, webviewPanel: vscode.WebviewPanel, token: vscode.CancellationToken): void | Thenable { @@ -540,12 +560,7 @@ class MapViewEditorProvider implements vscode.CustomTextEditorProvider { webviewPanel.title = title; webviewPanel.iconPath = vscode.Uri.parse(ResManager.GetInstance().GetIconByName('file_type_map.svg').ToUri()); webviewPanel.webview.html = this.genHtmlCont(title, 'No Content'); - webviewPanel.onDidDispose(() => { - if (this.fileWatcher) { - this.fileWatcher.Close(); - this.fileWatcher = undefined; - } - }); + webviewPanel.onDidDispose(() => this.deleteRef(viewFile.path, webviewPanel.webview)); if (!viewFile.IsFile()) { webviewPanel.webview.html = this.genHtmlCont(title, `Error: file '${viewFile.path}' is not a file !`); @@ -585,42 +600,88 @@ class MapViewEditorProvider implements vscode.CustomTextEditorProvider { return; } - const showMapView = () => { - try { - const execPath = ResManager.GetInstance().getBuilderDir() + File.sep + 'memap'; - const lines = ChildProcess - .execSync(`${execPath} -t ${toolName} -d ${fileDepth} "${mapFile.path}"`) - .toString().split(/\r\n|\n/); - - // append color - for (let index = 0; index < lines.length; index++) { - const line = lines[index]; - lines[index] = line - .replace(/\((\+[^0]\d*)\)/g, `($1)`) - .replace(/\((\-[^0]\d*)\)/g, `($1)`) - .replace(/^(\s*\|\s*)(Subtotals)/, `$1$2`) - .replace(/^(\s*Total)/, `\n$1`); - } + // auto update when file changed + try { - webviewPanel.webview.html = this.genHtmlCont(title, lines.join('\n')); - } catch (error) { - webviewPanel.webview.html = this.genHtmlCont(title, `Parse error: \r\n${error.message}`); - return; + let mInfo = this.mapViews.get(viewFile.path); + if (mInfo == undefined) { + mInfo = { watcher: new FileWatcher(mapFile, false), refList: [] }; + mInfo.watcher.OnChanged = () => this.showMapView(); + mInfo.watcher.Watch(); + this.mapViews.set(viewFile.path, mInfo); } - }; - if (this.fileWatcher == undefined) { - try { - this.fileWatcher = new FileWatcher(mapFile, false); - this.fileWatcher.OnChanged = () => showMapView(); - this.fileWatcher.Watch(); - } catch (error) { - this.fileWatcher?.Close(); - this.fileWatcher = undefined; + this.pushRef(viewFile.path, { + webview: webviewPanel.webview, + title: title, + toolName: toolName, + treeDepth: fileDepth, + mapPath: mapFile.path + }); + + } catch (error) { + // do nothing + } + + this.showMapView(); + } + + private pushRef(viewFilePath: string, item: MapViewRef) { + + const mInfo = this.mapViews.get(viewFilePath); + if (mInfo) { + const idx = mInfo.refList.findIndex((inf) => inf.webview == item.webview); + if (idx == -1) { + mInfo.refList.push(item); + } + } + } + + private deleteRef(viewFilePath: string, webview: vscode.Webview) { + + const mInfo = this.mapViews.get(viewFilePath); + if (mInfo) { + + const idx = mInfo.refList.findIndex((inf) => inf.webview == webview); + if (idx != -1) { + mInfo.refList.splice(idx, 1); + } + + if (mInfo.refList.length == 0) { + try { mInfo.watcher.Close(); } catch (error) { } + this.mapViews.delete(viewFilePath); } } + } + + private showMapView() { + + this.mapViews.forEach((mInfo) => { + + for (const vInfo of mInfo.refList) { + try { + const execPath = ResManager.GetInstance().getBuilderDir() + File.sep + 'memap'; + const lines = ChildProcess + .execSync(`${execPath} -t ${vInfo.toolName} -d ${vInfo.treeDepth} "${vInfo.mapPath}"`) + .toString().split(/\r\n|\n/); + + // append color + for (let index = 0; index < lines.length; index++) { + const line = lines[index]; + lines[index] = line + .replace(/\((\+[^0]\d*)\)/g, `($1)`) + .replace(/\((\-[^0]\d*)\)/g, `($1)`) + .replace(/^(\s*\|\s*)(Subtotals)/, `$1$2`) + .replace(/^(\s*Total)/, `\n$1`); + } + + vInfo.webview.html = this.genHtmlCont(vInfo.title, lines.join('\n')); - showMapView(); + } catch (error) { + vInfo.webview.html = this.genHtmlCont(vInfo.title, `Parse error: \r\n${error.message}`); + } + } + }); } private genHtmlCont(title: string, cont: string): string { From 92a21a6ca4223a1b30be339566da3593db8d8dcb Mon Sep 17 00:00:00 2001 From: github0null <2584456014@qq.com> Date: Mon, 29 Nov 2021 15:11:22 +0800 Subject: [PATCH 27/48] optimize code --- src/extension.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 093a2ae1..5702ab1e 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -560,7 +560,7 @@ class MapViewEditorProvider implements vscode.CustomTextEditorProvider { webviewPanel.title = title; webviewPanel.iconPath = vscode.Uri.parse(ResManager.GetInstance().GetIconByName('file_type_map.svg').ToUri()); webviewPanel.webview.html = this.genHtmlCont(title, 'No Content'); - webviewPanel.onDidDispose(() => this.deleteRef(viewFile.path, webviewPanel.webview)); + webviewPanel.onDidDispose(() => this.deleteRef(viewFile.path)); // delete all ref when panel closed if (!viewFile.IsFile()) { webviewPanel.webview.html = this.genHtmlCont(title, `Error: file '${viewFile.path}' is not a file !`); @@ -637,14 +637,20 @@ class MapViewEditorProvider implements vscode.CustomTextEditorProvider { } } - private deleteRef(viewFilePath: string, webview: vscode.Webview) { + private deleteRef(viewFilePath: string, webview?: vscode.Webview) { const mInfo = this.mapViews.get(viewFilePath); if (mInfo) { - const idx = mInfo.refList.findIndex((inf) => inf.webview == webview); - if (idx != -1) { - mInfo.refList.splice(idx, 1); + if (webview) { + const idx = mInfo.refList.findIndex((inf) => inf.webview == webview); + if (idx != -1) { + mInfo.refList[idx].webview = undefined; + mInfo.refList.splice(idx, 1); + } + } else { + mInfo.refList.forEach((inf) => inf.webview = undefined); + mInfo.refList = []; } if (mInfo.refList.length == 0) { From 5f84b57796e1fe0cc55cdb4400830456d9d88d99 Mon Sep 17 00:00:00 2001 From: github0null <2584456014@qq.com> Date: Mon, 29 Nov 2021 15:19:07 +0800 Subject: [PATCH 28/48] update --- src/extension.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 5702ab1e..82dace22 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -645,11 +645,11 @@ class MapViewEditorProvider implements vscode.CustomTextEditorProvider { if (webview) { const idx = mInfo.refList.findIndex((inf) => inf.webview == webview); if (idx != -1) { - mInfo.refList[idx].webview = undefined; + delete mInfo.refList[idx].webview; mInfo.refList.splice(idx, 1); } } else { - mInfo.refList.forEach((inf) => inf.webview = undefined); + mInfo.refList.forEach((inf) => delete inf.webview); mInfo.refList = []; } From dfa450d367f1c290841ffe8a7a317e33b024d337 Mon Sep 17 00:00:00 2001 From: null Date: Mon, 29 Nov 2021 20:28:50 +0800 Subject: [PATCH 29/48] optimize code --- src/EIDEProjectExplorer.ts | 16 +++++++++++++++- src/EIDETypeDefine.ts | 1 + src/extension.ts | 33 +++++++++++++++++---------------- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index 36f5415e..fbd97357 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -34,7 +34,7 @@ import { ResManager } from './ResManager'; import { GlobalEvent } from './GlobalEvents'; import { AbstractProject, CheckError, DataChangeType, VirtualSource } from './EIDEProject'; import { ToolchainName, ToolchainManager } from './ToolchainManager'; -import { CreateOptions, PackInfo, ComponentFileItem, DeviceInfo, getComponentKeyDescription, VirtualFolder, VirtualFile, ImportOptions, ProjectTargetInfo, ArmBaseCompileData } from './EIDETypeDefine'; +import { CreateOptions, PackInfo, ComponentFileItem, DeviceInfo, getComponentKeyDescription, VirtualFolder, VirtualFile, ImportOptions, ProjectTargetInfo, ArmBaseCompileData, ProjectConfigData } from './EIDETypeDefine'; import { WorkspaceManager } from './WorkspaceManager'; import { can_not_close_project, project_is_opened, project_load_failed, @@ -1530,6 +1530,20 @@ class ProjectDataProvider implements vscode.TreeDataProvider { // convert .EIDE to .eide this.toLowercaseEIDEFolder(targetDir); + // rename project name + { + const prjFile = File.fromArray([targetDir.path, AbstractProject.EIDE_DIR, AbstractProject.prjConfigName]); + if (!prjFile.IsFile()) throw Error(`project file: '${prjFile.path}' is not exist !`); + + try { + const prjConf: ProjectConfigData = JSON.parse(prjFile.Read()); + prjConf.name = option.name; // set project name + prjFile.Write(JSON.stringify(prjConf)); + } catch (error) { + throw Error(`change project name failed !, msg: ${error.message}`); + } + } + // switch workspace if user select `yes` const item = await vscode.window.showInformationMessage( view_str$operation$create_prj_done, 'Yes', 'Later' diff --git a/src/EIDETypeDefine.ts b/src/EIDETypeDefine.ts index 9fdeabf3..e5b5b9a2 100644 --- a/src/EIDETypeDefine.ts +++ b/src/EIDETypeDefine.ts @@ -442,6 +442,7 @@ export interface VirtualFolder { } export interface ProjectConfigData { + name: string; type: ProjectType; mode: string; // target name diff --git a/src/extension.ts b/src/extension.ts index 82dace22..693f7ab5 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -529,7 +529,9 @@ import { FileWatcher } from '../lib/node-utility/FileWatcher'; interface MapViewRef { - webview: vscode.Webview; + uid: string; + + vscWebview: vscode.Webview; title: string; @@ -556,11 +558,14 @@ class MapViewEditorProvider implements vscode.CustomTextEditorProvider { const viewFile = new File(document.fileName); const title = viewFile.noSuffixName; + // view uid + const uid = `${viewFile.path}-${Date.now().toString()}`; + // init webviewPanel.title = title; webviewPanel.iconPath = vscode.Uri.parse(ResManager.GetInstance().GetIconByName('file_type_map.svg').ToUri()); webviewPanel.webview.html = this.genHtmlCont(title, 'No Content'); - webviewPanel.onDidDispose(() => this.deleteRef(viewFile.path)); // delete all ref when panel closed + webviewPanel.onDidDispose(() => this.deleteRef(viewFile.path, uid)); if (!viewFile.IsFile()) { webviewPanel.webview.html = this.genHtmlCont(title, `Error: file '${viewFile.path}' is not a file !`); @@ -612,7 +617,8 @@ class MapViewEditorProvider implements vscode.CustomTextEditorProvider { } this.pushRef(viewFile.path, { - webview: webviewPanel.webview, + uid: uid, + vscWebview: webviewPanel.webview, title: title, toolName: toolName, treeDepth: fileDepth, @@ -630,27 +636,22 @@ class MapViewEditorProvider implements vscode.CustomTextEditorProvider { const mInfo = this.mapViews.get(viewFilePath); if (mInfo) { - const idx = mInfo.refList.findIndex((inf) => inf.webview == item.webview); + const idx = mInfo.refList.findIndex((inf) => inf.uid == item.uid); if (idx == -1) { mInfo.refList.push(item); } } } - private deleteRef(viewFilePath: string, webview?: vscode.Webview) { + private deleteRef(viewFilePath: string, uid: string) { const mInfo = this.mapViews.get(viewFilePath); if (mInfo) { - if (webview) { - const idx = mInfo.refList.findIndex((inf) => inf.webview == webview); - if (idx != -1) { - delete mInfo.refList[idx].webview; - mInfo.refList.splice(idx, 1); - } - } else { - mInfo.refList.forEach((inf) => delete inf.webview); - mInfo.refList = []; + const idx = mInfo.refList.findIndex((inf) => inf.uid == uid); + if (idx != -1) { + delete mInfo.refList[idx].vscWebview; + mInfo.refList.splice(idx, 1); } if (mInfo.refList.length == 0) { @@ -681,10 +682,10 @@ class MapViewEditorProvider implements vscode.CustomTextEditorProvider { .replace(/^(\s*Total)/, `\n$1`); } - vInfo.webview.html = this.genHtmlCont(vInfo.title, lines.join('\n')); + vInfo.vscWebview.html = this.genHtmlCont(vInfo.title, lines.join('\n')); } catch (error) { - vInfo.webview.html = this.genHtmlCont(vInfo.title, `Parse error: \r\n${error.message}`); + vInfo.vscWebview.html = this.genHtmlCont(vInfo.title, `Parse error: \r\n${error.message}`); } } }); From 14b73a47b6ee8ab585a851282f12f4a308d33c6c Mon Sep 17 00:00:00 2001 From: null Date: Wed, 1 Dec 2021 00:25:52 +0800 Subject: [PATCH 30/48] optimize vir folder --- .gitmodules | 3 -- package.nls.json | 9 +++- res/eide_makefile_template | 1 - src/EIDEProjectExplorer.ts | 99 +++++++++++++++++++++++--------------- src/OperationExplorer.ts | 4 +- src/StringTable.ts | 14 +++++- 6 files changed, 83 insertions(+), 47 deletions(-) delete mode 160000 res/eide_makefile_template diff --git a/.gitmodules b/.gitmodules index fecc9b31..876777b3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "res/eide_makefile_template"] - path = res/eide_makefile_template - url = git@github0null.io:root/eide_makefile_template.git [submodule "lib/node-utility"] path = lib/node-utility url = git@github.com:github0null/node-utility.git diff --git a/package.nls.json b/package.nls.json index 51da2b21..fb9647c5 100644 --- a/package.nls.json +++ b/package.nls.json @@ -16,7 +16,7 @@ "eide.project.save.all": "Save All Projects", "eide.project.active": "Active Project", "eide.project.close": "Close", - "eide.project.export.template": "Export Eide Template", + "eide.project.export.template": "Export Eide Project Template", "eide.project.export.keil": "Export Keil Project", "eide.project.show.commands": "Show Compiler CommandLine", "eide.project.switch.target": "Switch Target", @@ -27,6 +27,13 @@ "eide.project.gen.makefile": "Generate Makefile Template", "eide.project.modify.files.options": "Append Compiler Options For Files", + "eide.prj.menus.main.cppcheck": "Static Check", + "eide.prj.menus.sub.cppcheck.run": "Check Project by Cppcheck", + "eide.prj.menus.sub.cppcheck.clear": "Clear Cppcheck Diagnostic Informations", + "eide.prj.menus.main.export": "Export As ...", + "eide.prj.menus.main.export.keil": "Keil Project", + "eide.prj.menus.main.export.eide": "Eide Project Template", + "eide.workspace.build": "Build All", "eide.workspace.rebuild": "Rebuild All", "eide.workspace.open.config": "Open Workspace Configuration", diff --git a/res/eide_makefile_template b/res/eide_makefile_template deleted file mode 160000 index 771d32b4..00000000 --- a/res/eide_makefile_template +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 771d32b4ffc8d12e75ef15df3e3052135651f5ac diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index fbd97357..a9dc551f 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -59,7 +59,9 @@ import { view_str$settings$prjEnv, view_str$prompt$unresolved_deps, view_str$prompt$prj_location, - view_str$prompt$src_folder_must_be_a_child_of_root + view_str$prompt$src_folder_must_be_a_child_of_root, + view_str$project$folder_type_virtual_desc, + view_str$project$folder_type_fs_desc } from './StringTable'; import { CodeBuilder, BuildOptions } from './CodeBuilder'; import { ExceptionToMessage, newMessage } from './Message'; @@ -744,7 +746,7 @@ class ProjectDataProvider implements vscode.TreeDataProvider { value: vFolder.name, obj: { path: vFolderPath, vFolder: vFolder }, projectIndex: element.val.projectIndex, - tooltip: vFolder.name + tooltip: `${vFolder.name} (${vFolder.files.length} files, ${vFolder.folders.length} folders)` })); }); break; @@ -931,33 +933,39 @@ class ProjectDataProvider implements vscode.TreeDataProvider { const curFolder = element.val.obj; // put child folders - curFolder.vFolder.folders.forEach((vFolder) => { - const vFolderPath = `${curFolder.path}/${vFolder.name}`; - const isFolderExcluded = project.isExcluded(vFolderPath); - const itemType = isFolderExcluded ? TreeItemType.V_EXCFOLDER : TreeItemType.V_FOLDER; - iList.push(new ProjTreeItem(itemType, { - value: vFolder.name, - obj: { path: vFolderPath, vFolder: vFolder }, - projectIndex: element.val.projectIndex, - tooltip: isFolderExcluded ? view_str$project$excludeFolder : vFolder.name, - })); - }); + curFolder.vFolder.folders + .sort((a, b) => a.name.localeCompare(b.name)) + .forEach((vFolder) => { + const vFolderPath = `${curFolder.path}/${vFolder.name}`; + const isFolderExcluded = project.isExcluded(vFolderPath); + const itemType = isFolderExcluded ? TreeItemType.V_EXCFOLDER : TreeItemType.V_FOLDER; + iList.push(new ProjTreeItem(itemType, { + value: vFolder.name, + obj: { path: vFolderPath, vFolder: vFolder }, + projectIndex: element.val.projectIndex, + tooltip: isFolderExcluded + ? view_str$project$excludeFolder + : `${vFolder.name} (${vFolder.files.length} files, ${vFolder.folders.length} folders)`, + })); + }); // put child files - curFolder.vFolder.files.forEach((vFile) => { - const file = new File(project.ToAbsolutePath(vFile.path)); - const vFilePath = `${curFolder.path}/${file.name}`; - const isFileExcluded = project.isExcluded(vFilePath); - const itemType = isFileExcluded ? TreeItemType.V_EXCFILE_ITEM : TreeItemType.V_FILE_ITEM; - iList.push(new ProjTreeItem(itemType, { - value: file, - collapsibleState: project.getSourceRefs(file).length > 0 ? - vscode.TreeItemCollapsibleState.Collapsed : vscode.TreeItemCollapsibleState.None, - obj: { path: vFilePath, vFile: vFile }, - projectIndex: element.val.projectIndex, - tooltip: isFileExcluded ? view_str$project$excludeFile : file.path, - })); - }); + curFolder.vFolder.files + .sort((a, b) => a.path.localeCompare(b.path)) + .forEach((vFile) => { + const file = new File(project.ToAbsolutePath(vFile.path)); + const vFilePath = `${curFolder.path}/${file.name}`; + const isFileExcluded = project.isExcluded(vFilePath); + const itemType = isFileExcluded ? TreeItemType.V_EXCFILE_ITEM : TreeItemType.V_FILE_ITEM; + iList.push(new ProjTreeItem(itemType, { + value: file, + collapsibleState: project.getSourceRefs(file).length > 0 ? + vscode.TreeItemCollapsibleState.Collapsed : vscode.TreeItemCollapsibleState.None, + obj: { path: vFilePath, vFile: vFile }, + projectIndex: element.val.projectIndex, + tooltip: isFileExcluded ? view_str$project$excludeFile : file.path, + })); + }); } break; case TreeItemType.EXCFOLDER: @@ -1697,6 +1705,8 @@ interface BuildCommandInfo { export class ProjectExplorer { + private readonly vFolderNameMatcher = /^\w[\w\t \-:@\.]*$/; + private view: vscode.TreeView; private dataProvider: ProjectDataProvider; @@ -2496,16 +2506,27 @@ export class ProjectExplorer { const prj = this.dataProvider.GetProjectByIndex(item.val.projectIndex); - const folderType = await vscode.window.showQuickPick( - [view_str$project$folder_type_fs, view_str$project$folder_type_virtual], - { placeHolder: view_str$project$sel_folder_type }); + const folderType = await vscode.window.showQuickPick( + [ + { + label: view_str$project$folder_type_virtual, + detail: view_str$project$folder_type_virtual_desc + }, + { + label: view_str$project$folder_type_fs, + detail: view_str$project$folder_type_fs_desc + } + ], + { + placeHolder: view_str$project$sel_folder_type + }); if (folderType === undefined) { return; } // add folder from filesystem - if (folderType === view_str$project$folder_type_fs) { + if (folderType.label === view_str$project$folder_type_fs) { const folderList = await vscode.window.showOpenDialog({ canSelectMany: true, @@ -2540,15 +2561,16 @@ export class ProjectExplorer { } } - // add virtual folder + // add root virtual folder else { const folderName = await vscode.window.showInputBox({ - placeHolder: 'Input folder name', + placeHolder: 'Input a folder name', ignoreFocusOut: true, validateInput: (input) => { - if (!/^\w+$/.test(input)) { return `must match '^\\w+$'`; } - return undefined; + if (!this.vFolderNameMatcher.test(input)) { + return `must match '${this.vFolderNameMatcher.source}'`; + } } }); @@ -2626,11 +2648,12 @@ export class ProjectExplorer { const curFolder = item.val.obj; const folderName = await vscode.window.showInputBox({ - placeHolder: 'Input folder name', + placeHolder: 'Input a folder name', ignoreFocusOut: true, validateInput: (input) => { - if (!/^\w+$/.test(input)) { return `must match '^\\w+$'`; } - return undefined; + if (!this.vFolderNameMatcher.test(input)) { + return `must match '${this.vFolderNameMatcher.source}'`; + } } }); diff --git a/src/OperationExplorer.ts b/src/OperationExplorer.ts index 475d71da..a621a653 100644 --- a/src/OperationExplorer.ts +++ b/src/OperationExplorer.ts @@ -706,8 +706,8 @@ export class OperationExplorer { let prevGroupStack: TemplateGroup[] = []; let curTempGroup: TemplateGroup = templateGroup; - const goBackItemForGroup: vscode.QuickPickItem = { label: '..', description: 'Back' }; - const goBackItemForItem: vscode.QuickPickItem = { label: '..', detail: 'Back' }; + const goBackItemForGroup: vscode.QuickPickItem = { label: '..', description: 'Back', alwaysShow: true }; + const goBackItemForItem: vscode.QuickPickItem = { label: '..', detail: 'Back', alwaysShow: true }; // selection loop while (true) { diff --git a/src/StringTable.ts b/src/StringTable.ts index c24007b5..2555952d 100644 --- a/src/StringTable.ts +++ b/src/StringTable.ts @@ -210,8 +210,13 @@ export const view_str$project$sel_folder_type = [ ][langIndex]; export const view_str$project$folder_type_fs = [ - '文件系统文件夹', - 'Filesystem Folder' + '普通文件夹', + 'Normal Folder' +][langIndex]; + +export const view_str$project$folder_type_fs_desc = [ + '从磁盘中选择一个文件夹,eide 将其直接链接到项目中,并自动搜索和添加其中的源文件以及包含路径', + 'Select a folder from disk, eide will link it directly into your project, and automatically search and add source files and include paths to it.' ][langIndex]; export const view_str$project$folder_type_virtual = [ @@ -219,6 +224,11 @@ export const view_str$project$folder_type_virtual = [ 'Virtual Folder' ][langIndex]; +export const view_str$project$folder_type_virtual_desc = [ + '新建一个虚拟文件夹(该文件夹在磁盘上是不存在的)来组织源文件的结构', + 'Create a VirtualFolder (The folder does not exist on disk) to organize the source file structure.' +][langIndex]; + export const view_str$project$add_source = [ '添加源文件', 'Add Source Files' From 4f9e10f6847e743414a7ad8deb681cf49eae264e Mon Sep 17 00:00:00 2001 From: github0null <2584456014@qq.com> Date: Wed, 1 Dec 2021 18:02:07 +0800 Subject: [PATCH 31/48] update --- package.json | 2 +- src/EIDEProject.ts | 12 ++++-------- src/EIDEProjectExplorer.ts | 33 +++++++++++++++++++++++++++------ src/EIDETypeDefine.ts | 21 +++++++++++++++------ 4 files changed, 47 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index bce6fa93..47bcd771 100644 --- a/package.json +++ b/package.json @@ -1370,4 +1370,4 @@ } ] } -} \ No newline at end of file +} diff --git a/src/EIDEProject.ts b/src/EIDEProject.ts index 7aa5f6e4..c5a23ae8 100644 --- a/src/EIDEProject.ts +++ b/src/EIDEProject.ts @@ -122,12 +122,8 @@ export class VirtualSource implements SourceProvider { return path.startsWith(VirtualSource.rootName); } - private getRoot(): VirtualFolder { - return { - name: VirtualSource.rootName, - files: [], - folders: this.config.virtualFolder - }; + public getRoot(): VirtualFolder { + return this.config.virtualFolder; } private getFolderByName(vFolder: VirtualFolder, name: string): VirtualFolder | undefined { @@ -860,8 +856,8 @@ export abstract class AbstractProject { return this.sourceRoots.getRootFolderList(); } - getVirtualSourceRootFolders(): VirtualFolder[] { - return this.virtualSource.getFolder()?.folders || []; + getVirtualSourceRoot(): VirtualFolder { + return this.virtualSource.getRoot(); } getVirtualSourceManager(): VirtualSource { diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index a9dc551f..a4da9858 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -736,8 +736,9 @@ class ProjectDataProvider implements vscode.TreeDataProvider { 'StatusWarning_16x.svg' : (isComponent ? 'DependencyGraph_16x.svg' : undefined) })); }); + // push virtual source folder - project.getVirtualSourceRootFolders() + project.getVirtualSourceRoot().folders .sort((folder1, folder2) => { return folder1.name.localeCompare(folder2.name); }) .forEach((vFolder) => { const vFolderPath = `${VirtualSource.rootName}/${vFolder.name}`; @@ -749,6 +750,24 @@ class ProjectDataProvider implements vscode.TreeDataProvider { tooltip: `${vFolder.name} (${vFolder.files.length} files, ${vFolder.folders.length} folders)` })); }); + + // put virtual source files + project.getVirtualSourceRoot().files + .sort((a, b) => a.path.localeCompare(b.path)) + .forEach((vFile) => { + const file = new File(project.ToAbsolutePath(vFile.path)); + const vFilePath = `${VirtualSource.rootName}/${file.name}`; + const isFileExcluded = project.isExcluded(vFilePath); + const itemType = isFileExcluded ? TreeItemType.V_EXCFILE_ITEM : TreeItemType.V_FILE_ITEM; + iList.push(new ProjTreeItem(itemType, { + value: file, + collapsibleState: project.getSourceRefs(file).length > 0 ? + vscode.TreeItemCollapsibleState.Collapsed : vscode.TreeItemCollapsibleState.None, + obj: { path: vFilePath, vFile: vFile }, + projectIndex: element.val.projectIndex, + tooltip: isFileExcluded ? view_str$project$excludeFile : file.path, + })); + }); break; case TreeItemType.PACK: { @@ -1269,7 +1288,11 @@ class ProjectDataProvider implements vscode.TreeDataProvider { const projectInfo = baseInfo.prjConfig.config; // init project info - projectInfo.virtualFolder = []; + projectInfo.virtualFolder = { + name: VirtualSource.rootName, + files: [], + folders: [] + }; const getVirtualFolder = (path: string, noCreate?: boolean): VirtualFolder | undefined => { @@ -1280,10 +1303,8 @@ class ProjectDataProvider implements vscode.TreeDataProvider { const pathList = path.split('/'); pathList.splice(0, 1); // remvoe root - let curFolder: VirtualFolder = { - name: VirtualSource.rootName, files: [], - folders: projectInfo.virtualFolder - }; + // init start search folder + let curFolder: VirtualFolder = projectInfo.virtualFolder; for (const name of pathList) { const index = curFolder.folders.findIndex((folder) => { return folder.name === name; }); diff --git a/src/EIDETypeDefine.ts b/src/EIDETypeDefine.ts index e5b5b9a2..66c28686 100644 --- a/src/EIDETypeDefine.ts +++ b/src/EIDETypeDefine.ts @@ -60,12 +60,12 @@ import * as os from 'os'; import * as vscode from 'vscode'; import * as NodePath from 'path'; import { isNullOrUndefined } from "util"; -import { AbstractProject } from "./EIDEProject"; +import { AbstractProject, VirtualSource } from "./EIDEProject"; import { SettingManager } from "./SettingManager"; import { jsonc } from 'jsonc'; import { WorkspaceManager } from "./WorkspaceManager"; -import * as utility from './utility' +import * as utility from './utility'; // ------------------------------------------- @@ -460,7 +460,7 @@ export interface ProjectConfigData { // source srcDirs: string[]; - virtualFolder: VirtualFolder[]; + virtualFolder: VirtualFolder; dependenceList: DependenceGroup[]; outDir: string; @@ -493,6 +493,15 @@ export class ProjectConfiguration constructor(f: File, type?: ProjectType) { super(f, type); + // compate old version + if (Array.isArray(this.config.virtualFolder)) { + this.config.virtualFolder = { + name: VirtualSource.rootName, + files: [], + folders: this.config.virtualFolder + }; + } + this.compileConfigModel = CompileConfigModel.getInstance(this.config); this.uploadConfigModel = UploadConfigModel.getInstance(this.config.uploader); @@ -592,7 +601,7 @@ export class ProjectConfiguration dependenceList: [], compileConfig: SdccCompileConfigModel.getDefaultConfig(), srcDirs: [], - virtualFolder: [], + virtualFolder: { name: VirtualSource.rootName, files: [], folders: [] }, excludeList: [], outDir: '.\\build', deviceName: null, @@ -613,7 +622,7 @@ export class ProjectConfiguration compileConfig: GccCompileConfigModel.getDefaultConfig(), uploader: 'JLink', srcDirs: [], - virtualFolder: [], + virtualFolder: { name: VirtualSource.rootName, files: [], folders: [] }, excludeList: [], outDir: '.\\build', deviceName: null, @@ -634,7 +643,7 @@ export class ProjectConfiguration compileConfig: RiscvCompileConfigModel.getDefaultConfig(), uploader: 'JLink', srcDirs: [], - virtualFolder: [], + virtualFolder: { name: VirtualSource.rootName, files: [], folders: [] }, excludeList: [], outDir: '.\\build', deviceName: null, From f6512f209ae12d653210aebd64246e3a20ac333c Mon Sep 17 00:00:00 2001 From: null Date: Thu, 2 Dec 2021 00:06:10 +0800 Subject: [PATCH 32/48] optimize code, support source importer --- package.json | 14 ++- package.nls.json | 3 +- package.nls.zh-CN.json | 3 +- src/EIDEProject.ts | 2 +- src/EIDEProjectExplorer.ts | 196 +++++++++++++++++++++++++++---------- src/EIDETypeDefine.ts | 10 +- src/HexUploader.ts | 2 +- src/KeilXmlParser.ts | 2 +- src/Platform.ts | 2 +- src/extension.ts | 1 + 10 files changed, 174 insertions(+), 61 deletions(-) diff --git a/package.json b/package.json index 47bcd771..4288c20e 100644 --- a/package.json +++ b/package.json @@ -509,6 +509,14 @@ "light": "./res/icon/ConfigurationFile_16x.svg" } }, + { + "command": "_cl.eide.project.import.ext.source.struct", + "title": "%eide.project.import.ext.project.src.struct%", + "icon": { + "dark": "./res/icon/Import_16x.svg", + "light": "./res/icon/Import_16x.svg" + } + }, { "command": "_cl.eide.project.cppcheck.check_all", "title": "%eide.project.run.cppcheck%" @@ -1022,7 +1030,7 @@ }, { "command": "_cl.eide.project.source.virtual_folder_add_file", - "when": "viewItem == V_FOLDER_ROOT || viewItem == V_FOLDER || viewItem == V_EXCFOLDER && view == Project" + "when": "viewItem == PROJECT || viewItem == V_FOLDER_ROOT || viewItem == V_FOLDER || viewItem == V_EXCFOLDER && view == Project" }, { "command": "_cl.eide.project.source.virtual_folder_add", @@ -1149,6 +1157,10 @@ "command": "_cl.eide.project.modify.files.options", "when": "viewItem == PROJECT && view == Project" }, + { + "command": "_cl.eide.project.import.ext.source.struct", + "when": "viewItem == PROJECT && view == Project" + }, { "command": "_cl.eide.project.sourceRoot.refresh", "group": "inline", diff --git a/package.nls.json b/package.nls.json index fb9647c5..8e0c9ba2 100644 --- a/package.nls.json +++ b/package.nls.json @@ -25,7 +25,8 @@ "eide.project.clean": "Clean", "eide.project.upload": "Upload Program To Device", "eide.project.gen.makefile": "Generate Makefile Template", - "eide.project.modify.files.options": "Append Compiler Options For Files", + "eide.project.modify.files.options": "Append separate compiler options to the file", + "eide.project.import.ext.project.src.struct": "Import source file resources from other IDE's project", "eide.prj.menus.main.cppcheck": "Static Check", "eide.prj.menus.sub.cppcheck.run": "Check Project by Cppcheck", diff --git a/package.nls.zh-CN.json b/package.nls.zh-CN.json index 20418f1e..51a73b2d 100644 --- a/package.nls.zh-CN.json +++ b/package.nls.zh-CN.json @@ -25,7 +25,8 @@ "eide.project.clean": "清理", "eide.project.upload": "烧录", "eide.project.gen.makefile": "生成 Makefile 模板", - "eide.project.modify.files.options": "向文件附加编译选项", + "eide.project.modify.files.options": "为文件附加单独的编译选项", + "eide.project.import.ext.project.src.struct": "从其他 IDE 的项目中导入源文件资源", "eide.workspace.build": "构建所有项目", "eide.workspace.rebuild": "重新构建所有项目", diff --git a/src/EIDEProject.ts b/src/EIDEProject.ts index c5a23ae8..1c967afa 100644 --- a/src/EIDEProject.ts +++ b/src/EIDEProject.ts @@ -897,7 +897,7 @@ export abstract class AbstractProject { } ToAbsolutePath(path: string): string { - if (!NodePath.isAbsolute(path)) { + if (!File.isAbsolute(path)) { return NodePath.normalize(this.GetRootDir().path + NodePath.sep + path); } return NodePath.normalize(path); diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index a4da9858..274f89c0 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -672,7 +672,8 @@ class ProjectDataProvider implements vscode.TreeDataProvider { iList.push(new ProjTreeItem(TreeItemType.PROJECT, { value: view_str$project$title, projectIndex: element.val.projectIndex, - tooltip: view_str$project$title + tooltip: view_str$project$title, + obj: { path: VirtualSource.rootName, vFolder: project.getVirtualSourceRoot() } })); if (prjType === 'ARM') { // only display for ARM project @@ -717,57 +718,59 @@ class ProjectDataProvider implements vscode.TreeDataProvider { } break; case TreeItemType.PROJECT: - // push filesystem source folder - project.getSourceRootFolders() - .sort((info_1, info_2) => { - const isComponent = info_1.displayName === DependenceManager.DEPENDENCE_DIR; - return isComponent ? -1 : info_1.displayName.localeCompare(info_2.displayName); - }) - .forEach((rootInfo) => { - const isComponent = rootInfo.displayName === DependenceManager.DEPENDENCE_DIR; - const folderDispName = isComponent ? view_str$project$cmsis_components : rootInfo.displayName; - iList.push(new ProjTreeItem(TreeItemType.FOLDER_ROOT, { - value: folderDispName, - obj: rootInfo.fileWatcher.file, - projectIndex: element.val.projectIndex, - contextVal: isComponent ? 'FOLDER_ROOT_DEPS' : undefined, - tooltip: rootInfo.needUpdate ? view_str$project$needRefresh : folderDispName, - icon: rootInfo.needUpdate ? - 'StatusWarning_16x.svg' : (isComponent ? 'DependencyGraph_16x.svg' : undefined) - })); - }); + { + // push filesystem source folder + project.getSourceRootFolders() + .sort((info_1, info_2) => { + const isComponent = info_1.displayName === DependenceManager.DEPENDENCE_DIR; + return isComponent ? -1 : info_1.displayName.localeCompare(info_2.displayName); + }) + .forEach((rootInfo) => { + const isComponent = rootInfo.displayName === DependenceManager.DEPENDENCE_DIR; + const folderDispName = isComponent ? view_str$project$cmsis_components : rootInfo.displayName; + iList.push(new ProjTreeItem(TreeItemType.FOLDER_ROOT, { + value: folderDispName, + obj: rootInfo.fileWatcher.file, + projectIndex: element.val.projectIndex, + contextVal: isComponent ? 'FOLDER_ROOT_DEPS' : undefined, + tooltip: rootInfo.needUpdate ? view_str$project$needRefresh : folderDispName, + icon: rootInfo.needUpdate ? + 'StatusWarning_16x.svg' : (isComponent ? 'DependencyGraph_16x.svg' : undefined) + })); + }); - // push virtual source folder - project.getVirtualSourceRoot().folders - .sort((folder1, folder2) => { return folder1.name.localeCompare(folder2.name); }) - .forEach((vFolder) => { - const vFolderPath = `${VirtualSource.rootName}/${vFolder.name}`; - const itemType = project.isExcluded(vFolderPath) ? TreeItemType.V_EXCFOLDER : TreeItemType.V_FOLDER_ROOT; - iList.push(new ProjTreeItem(itemType, { - value: vFolder.name, - obj: { path: vFolderPath, vFolder: vFolder }, - projectIndex: element.val.projectIndex, - tooltip: `${vFolder.name} (${vFolder.files.length} files, ${vFolder.folders.length} folders)` - })); - }); + // push virtual source folder + project.getVirtualSourceRoot().folders + .sort((folder1, folder2) => { return folder1.name.localeCompare(folder2.name); }) + .forEach((vFolder) => { + const vFolderPath = `${VirtualSource.rootName}/${vFolder.name}`; + const itemType = project.isExcluded(vFolderPath) ? TreeItemType.V_EXCFOLDER : TreeItemType.V_FOLDER_ROOT; + iList.push(new ProjTreeItem(itemType, { + value: vFolder.name, + obj: { path: vFolderPath, vFolder: vFolder }, + projectIndex: element.val.projectIndex, + tooltip: `${vFolder.name} (${vFolder.files.length} files, ${vFolder.folders.length} folders)` + })); + }); - // put virtual source files - project.getVirtualSourceRoot().files - .sort((a, b) => a.path.localeCompare(b.path)) - .forEach((vFile) => { - const file = new File(project.ToAbsolutePath(vFile.path)); - const vFilePath = `${VirtualSource.rootName}/${file.name}`; - const isFileExcluded = project.isExcluded(vFilePath); - const itemType = isFileExcluded ? TreeItemType.V_EXCFILE_ITEM : TreeItemType.V_FILE_ITEM; - iList.push(new ProjTreeItem(itemType, { - value: file, - collapsibleState: project.getSourceRefs(file).length > 0 ? - vscode.TreeItemCollapsibleState.Collapsed : vscode.TreeItemCollapsibleState.None, - obj: { path: vFilePath, vFile: vFile }, - projectIndex: element.val.projectIndex, - tooltip: isFileExcluded ? view_str$project$excludeFile : file.path, - })); - }); + // put virtual source files + project.getVirtualSourceRoot().files + .sort((a, b) => a.path.localeCompare(b.path)) + .forEach((vFile) => { + const file = new File(project.ToAbsolutePath(vFile.path)); + const vFilePath = `${VirtualSource.rootName}/${file.name}`; + const isFileExcluded = project.isExcluded(vFilePath); + const itemType = isFileExcluded ? TreeItemType.V_EXCFILE_ITEM : TreeItemType.V_FILE_ITEM; + iList.push(new ProjTreeItem(itemType, { + value: file, + collapsibleState: project.getSourceRefs(file).length > 0 ? + vscode.TreeItemCollapsibleState.Collapsed : vscode.TreeItemCollapsibleState.None, + obj: { path: vFilePath, vFile: vFile }, + projectIndex: element.val.projectIndex, + tooltip: isFileExcluded ? view_str$project$excludeFile : file.path, + })); + }); + } break; case TreeItemType.PACK: { @@ -1289,7 +1292,7 @@ class ProjectDataProvider implements vscode.TreeDataProvider { // init project info projectInfo.virtualFolder = { - name: VirtualSource.rootName, + name: VirtualSource.rootName, files: [], folders: [] }; @@ -1724,6 +1727,12 @@ interface BuildCommandInfo { order?: number; } +interface ImporterProjectInfo { + incList: string[]; + defineList: string[]; + files: VirtualFolder; +} + export class ProjectExplorer { private readonly vFolderNameMatcher = /^\w[\w\t \-:@\.]*$/; @@ -3211,6 +3220,91 @@ export class ProjectExplorer { } } + async ImportSourceFromExtProject(item: ProjTreeItem) { + + try { + // + // select importer + // + const scriptRoot = File.fromArray([ResManager.GetInstance().GetBinDir().path, 'scripts']); + const imptrFolder = File.fromArray([scriptRoot.path, 'importer']); + const items: any[] = []; + + imptrFolder.GetList([/^(?:[^\.]+)\.(?:[^\.]+)\.js$/i]) + .forEach((imptrFile) => { + const m = /^(?[^\.]+)\.(?[^\.]+)\.js$/i.exec(imptrFile.name); + if (m && m.groups) { + items.push({ + label: m.groups['type'].replace(/\-/g, ' ').replace(/_/g, ' '), + detail: `project file suffix: '${m.groups['suffix']}'`, + suffix: m.groups['suffix'], + file: imptrFile + }); + } + }); + + const imptrType: any = await vscode.window.showQuickPick(items, { + placeHolder: `Select an importer`, + canPickMany: false + }); + + if (imptrType == undefined) { + return; + } + + const filter: any = {}; + filter[imptrType.label] = [imptrType.suffix]; + + const uri = await vscode.window.showOpenDialog({ + openLabel: 'Import This File', + canSelectFiles: true, + filters: filter + }); + + if (uri == undefined) { + return; + } + + // + // run importer + // + const prjFile = new File(uri[0].fsPath); + const imptrName = (imptrType.file).noSuffixName; + const cmds = ['--std', './importer/index.js', imptrName, prjFile.path]; + const result = child_process.execFileSync(`${scriptRoot.path}/qjs.exe`, cmds, { cwd: scriptRoot.path }).toString(); + + let prjInfo: ImporterProjectInfo; + try { + prjInfo = JSON.parse(result); + } catch (error) { + GlobalEvent.emit('msg', newMessage(`Error`, `Import Error !, msg: '${result}'`)); + return; + } + + // + // start import project + // + const prj = this.dataProvider.GetProjectByIndex(item.val.projectIndex); + const prjConf = prj.GetConfiguration(); + prjConf.config.virtualFolder = prjInfo.files; + const deps = prjConf.CustomDep_getDependence(); + deps.incList = prjInfo.incList; + deps.libList = []; + deps.defineList = prjInfo.defineList; + + // + // notify update + // + prj.getVirtualSourceManager().load(); + prjConf.CustomDep_NotifyChanged(); + + GlobalEvent.emit('msg', newMessage('Info', 'Import Done !')); + + } catch (error) { + GlobalEvent.emit('error', error); + } + } + async AddIncludeDir(prjIndex: number) { const prj = this.dataProvider.GetProjectByIndex(prjIndex); const uri = await vscode.window.showOpenDialog({ diff --git a/src/EIDETypeDefine.ts b/src/EIDETypeDefine.ts index 66c28686..c6c980f8 100644 --- a/src/EIDETypeDefine.ts +++ b/src/EIDETypeDefine.ts @@ -532,7 +532,7 @@ export class ProjectConfiguration private toAbsolutePath(path: string): string { const _path = path.trim(); - if (NodePath.isAbsolute(_path)) { + if (File.isAbsolute(_path)) { return _path; } return NodePath.normalize(this.getRootDir().path + File.sep + _path); @@ -540,12 +540,16 @@ export class ProjectConfiguration private toRelativePath(path: string): string { - if (!NodePath.isAbsolute(path)) { + if (File.isEnvPath(path)) { // env path have no repath + return path; + } + + if (!File.isAbsolute(path)) { return path; } const rePath = NodePath.relative(this.getRootDir().path, path); - if (NodePath.isAbsolute(rePath)) { + if (File.isAbsolute(rePath)) { return rePath; } diff --git a/src/HexUploader.ts b/src/HexUploader.ts index f8cf96ff..23cd6473 100644 --- a/src/HexUploader.ts +++ b/src/HexUploader.ts @@ -165,7 +165,7 @@ export abstract class HexUploader { protected toAbsolute(_path: string): File { const nomalPath = NodePath.normalize(_path); - const file = NodePath.isAbsolute(nomalPath) ? + const file = File.isAbsolute(nomalPath) ? new File(nomalPath) : File.fromArray([this.project.GetRootDir().path, nomalPath]); return file; } diff --git a/src/KeilXmlParser.ts b/src/KeilXmlParser.ts index 18675211..78d8800d 100644 --- a/src/KeilXmlParser.ts +++ b/src/KeilXmlParser.ts @@ -181,7 +181,7 @@ export abstract class KeilParser { // example: file: 'c:\aa\bb', path: '../cc/f.txt', result: 'c:\aa\cc\f.txt' protected ToAbsolutePath(path: string): string { - if (NodePath.isAbsolute(path)) { + if (File.isAbsolute(path)) { return path.replace(/\//g, '\\'); } else { return NodePath.normalize(this._file.dir + File.sep + path); diff --git a/src/Platform.ts b/src/Platform.ts index 3f547787..063406e0 100644 --- a/src/Platform.ts +++ b/src/Platform.ts @@ -80,7 +80,7 @@ export function find(fileName: string): string | undefined { { windowsHide: true, encoding: 'ascii', shell: 'cmd' }).split(/\r\n|\n/); if (nameList.length > 0) { const path = nameList[0].replace(/"/g, ''); - if (NodePath.isAbsolute(path)) { + if (File.isAbsolute(path)) { return path; } } diff --git a/src/extension.ts b/src/extension.ts index 693f7ab5..08dd6472 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -157,6 +157,7 @@ export async function activate(context: vscode.ExtensionContext) { subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.showLibDir', (item) => projectExplorer.showLibDir(item.val.projectIndex))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.modifyOtherSettings', (item) => projectExplorer.ModifyOtherSettings(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.import.ext.source.struct', (item) => projectExplorer.ImportSourceFromExtProject(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.modify.deps', (item) => projectExplorer.ModifyCustomDependence(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.removeDependenceItem', (item) => projectExplorer.RemoveDependenceItem(item))); From 2a78d99c1a1e1b6b7b32a8b5fbf82962c54bfb4f Mon Sep 17 00:00:00 2001 From: null Date: Thu, 2 Dec 2021 00:09:21 +0800 Subject: [PATCH 33/48] Update node-utility --- lib/node-utility | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/node-utility b/lib/node-utility index 6fdbedd7..c0d27dc5 160000 --- a/lib/node-utility +++ b/lib/node-utility @@ -1 +1 @@ -Subproject commit 6fdbedd70d2b62b812e2d93498601c91e061edd5 +Subproject commit c0d27dc55bcc0cae31444e28b825c7357f925508 From bee39e875b9f73f490c38bc21c88fd472bf5244c Mon Sep 17 00:00:00 2001 From: null Date: Thu, 2 Dec 2021 00:15:19 +0800 Subject: [PATCH 34/48] update submodule --- lib/node-utility | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/node-utility b/lib/node-utility index c0d27dc5..c34a26b5 160000 --- a/lib/node-utility +++ b/lib/node-utility @@ -1 +1 @@ -Subproject commit c0d27dc55bcc0cae31444e28b825c7357f925508 +Subproject commit c34a26b5f589ff1aea8f2b46f9917b55ae4afb98 From 5f6a4ed04ebadefe7f0a4aaf94f4343104a20099 Mon Sep 17 00:00:00 2001 From: null Date: Thu, 2 Dec 2021 23:17:33 +0800 Subject: [PATCH 35/48] optimize for unify builder --- lang/stm8.iar.verify.json | 2 +- package.json | 8 +++- src/CodeBuilder.ts | 19 ++++++--- src/EIDEProjectExplorer.ts | 79 +++++++++++++++++++++++--------------- src/SettingManager.ts | 6 ++- src/ToolchainManager.ts | 6 +-- 6 files changed, 78 insertions(+), 42 deletions(-) diff --git a/lang/stm8.iar.verify.json b/lang/stm8.iar.verify.json index 82d0e575..38a9b5bb 100644 --- a/lang/stm8.iar.verify.json +++ b/lang/stm8.iar.verify.json @@ -504,7 +504,7 @@ "linker-config": { "readable_name": "Linker config file path", "readable_name.zh-cn": "链接脚本路径", - "description": "linker config file path.\n Example: \"lnkstm8xxx.icf\"\n or \"./lnkstm8xxx.icf\" (relative by workspace folder)\n or \"${ToolDir}/stm8/config/lnkstm8xxx.icf\"", + "description": "linker config file path.\n Example: \"lnkstm8xxx.icf\"\n or \"./lnkstm8xxx.icf\" (relative by workspace folder)\n or \"${ToolchainRoot}/stm8/config/lnkstm8xxx.icf\"", "type": "string", "default": "lnkstm8s103f3.icf" }, diff --git a/package.json b/package.json index 4288c20e..7cf2d58b 100644 --- a/package.json +++ b/package.json @@ -207,7 +207,13 @@ "type": "boolean", "scope": "resource", "markdownDescription": "%settings.builder.gen.makefile.params%", - "default": true + "default": false + }, + "EIDE.Builder.AdditionalCommandLine": { + "type": "string", + "scope": "resource", + "markdownDescription": "Append additional commandline when invoke unify_builder", + "default": "" }, "EIDE.Option.ShowToolbarInEditerTitle": { "type": "boolean", diff --git a/src/CodeBuilder.ts b/src/CodeBuilder.ts index 5c1c534a..9ae92386 100644 --- a/src/CodeBuilder.ts +++ b/src/CodeBuilder.ts @@ -142,10 +142,11 @@ export abstract class CodeBuilder { for (const expr in parttenInfo) { const path = (srcInf[fieldName]).replace(/\\/g, '/'); if (globmatch.isMatch(path, expr)) { + const val = parttenInfo[expr]?.trim().replace(/(?:\r\n|\n)$/, '') if (srcParams[srcInf.path]) { - srcParams[srcInf.path] += ' ' + (parttenInfo[expr] || '') + srcParams[srcInf.path] += ` ${val || ''}` } else { - srcParams[srcInf.path] = parttenInfo[expr] || ''; + srcParams[srcInf.path] = val || ''; } } } @@ -347,7 +348,8 @@ export abstract class CodeBuilder { .compileConfigModel.getOptions(this.project.getEideDir().path, config); const memMaxSize = this.getMaxSize(); const modeList: string[] = []; - const prevParams: BuilderParams = File.IsFile(paramsPath) ? JSON.parse(fs.readFileSync(paramsPath, 'utf8')) : {}; + const oldParamsPath = `${paramsPath}.old`; + const prevParams: BuilderParams = File.IsFile(oldParamsPath) ? JSON.parse(fs.readFileSync(oldParamsPath, 'utf8')) : {}; const sourceInfo = this.genSourceInfo(prevParams); const builderOptions: BuilderParams = { @@ -453,12 +455,19 @@ export abstract class CodeBuilder { } } - return [ + let cmds = [ '-b', binDir, '-M', toolchain.modelName, '-p', paramsPath, '-m', modeList.join('-') ]; + + const extraCmd = settingManager.getBuilderAdditionalCommandLine()?.trim(); + if (extraCmd) { + cmds = cmds.concat(extraCmd.split(/\s+/)); + } + + return cmds; } private getBuilderExe(): File { @@ -885,7 +894,7 @@ class ARMCodeBuilder extends CodeBuilder { extraCommands.push({ name: 'axf to elf', - command: `"\${exeDir}\\mono.exe" "\${exeDir}\\axf2elf.exe" -d "${tool_root_folder}" -b "${ouput_path}.bin" -i "${ouput_path}.axf" -o "${ouput_path}.elf" > "${axf2elf_log}"` + command: `"\${BuilderFolder}\\mono.exe" "\${BuilderFolder}\\axf2elf.exe" -d "${tool_root_folder}" -b "${ouput_path}.bin" -i "${ouput_path}.axf" -o "${ouput_path}.elf" > "${axf2elf_log}"` }); } diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index 274f89c0..09caadfe 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -3265,40 +3265,57 @@ export class ProjectExplorer { return; } - // - // run importer - // - const prjFile = new File(uri[0].fsPath); - const imptrName = (imptrType.file).noSuffixName; - const cmds = ['--std', './importer/index.js', imptrName, prjFile.path]; - const result = child_process.execFileSync(`${scriptRoot.path}/qjs.exe`, cmds, { cwd: scriptRoot.path }).toString(); - - let prjInfo: ImporterProjectInfo; - try { - prjInfo = JSON.parse(result); - } catch (error) { - GlobalEvent.emit('msg', newMessage(`Error`, `Import Error !, msg: '${result}'`)); - return; - } + await vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + title: `Importing Resources` + }, (progress) => { + return new Promise((resolve) => { + try { - // - // start import project - // - const prj = this.dataProvider.GetProjectByIndex(item.val.projectIndex); - const prjConf = prj.GetConfiguration(); - prjConf.config.virtualFolder = prjInfo.files; - const deps = prjConf.CustomDep_getDependence(); - deps.incList = prjInfo.incList; - deps.libList = []; - deps.defineList = prjInfo.defineList; + progress.report({ message: `running importer ...` }); + + // + // run importer + // + const prjFile = new File(uri[0].fsPath); + const imptrName = (imptrType.file).noSuffixName; + const cmds = ['--std', './importer/index.js', imptrName, prjFile.path]; + const result = child_process.execFileSync(`${scriptRoot.path}/qjs.exe`, cmds, { cwd: scriptRoot.path }).toString(); + + let prjInfo: ImporterProjectInfo; + try { + prjInfo = JSON.parse(result); + } catch (error) { + throw new Error(`Import Error !, msg: '${result}'`); + } - // - // notify update - // - prj.getVirtualSourceManager().load(); - prjConf.CustomDep_NotifyChanged(); + // + // start import project + // + const prj = this.dataProvider.GetProjectByIndex(item.val.projectIndex); + const prjConf = prj.GetConfiguration(); + prjConf.config.virtualFolder = prjInfo.files; + const deps = prjConf.CustomDep_getDependence(); + deps.incList = prjInfo.incList; + deps.libList = []; + deps.defineList = prjInfo.defineList; + + // + // notify update + // + prj.getVirtualSourceManager().load(); + prjConf.CustomDep_NotifyChanged(); + + // show message and exit + progress.report({ message: `done !` }); + setTimeout(() => resolve(), 1000); - GlobalEvent.emit('msg', newMessage('Info', 'Import Done !')); + } catch (error) { + GlobalEvent.emit('error', error); + resolve(); + } + }); + }); } catch (error) { GlobalEvent.emit('error', error); diff --git a/src/SettingManager.ts b/src/SettingManager.ts index 8ecd1bfd..ae2c31b5 100644 --- a/src/SettingManager.ts +++ b/src/SettingManager.ts @@ -242,8 +242,12 @@ export class SettingManager { //--------------------- Global Option ------------------------ + getBuilderAdditionalCommandLine(): string | undefined { + return this.getConfiguration().get('Builder.AdditionalCommandLine'); + } + getMapViewParserDepth(): number { - return this.getConfiguration().get('Option.MapViewParserDepth') || 1; + return this.getConfiguration().get('Option.MapViewParserDepth') || 3; } isDisplaySourceRefs(): boolean { diff --git a/src/ToolchainManager.ts b/src/ToolchainManager.ts index e0379c2c..d48dc7eb 100644 --- a/src/ToolchainManager.ts +++ b/src/ToolchainManager.ts @@ -1318,9 +1318,9 @@ class IARSTM8 implements IToolchian { options.linker['linker-config'] = `"${prjInfo.toAbsolutePath(options.linker['linker-config'])}"`; } - // use toolchain root folder, like ${ToolDir}\stm8\config - else if (linkerConfig.toLowerCase().startsWith('${tooldir}')) { - const absPath = (options.linker['linker-config']).replace(/\$\{ToolDir\}/i, this.getToolchainDir().path); + // use toolchain root folder, like ${ToolchainRoot}\stm8\config + else if (linkerConfig.toLowerCase().startsWith('${ToolchainRoot}')) { + const absPath = (options.linker['linker-config']).replace(/\$\{ToolchainRoot\}/i, this.getToolchainDir().path); options.linker['linker-config'] = `"${NodePath.normalize(absPath)}"`; } } From 7af1b92d975cd99152ff2a3f90b54673de9aa4cd Mon Sep 17 00:00:00 2001 From: null Date: Sat, 4 Dec 2021 02:30:33 +0800 Subject: [PATCH 36/48] allow show file folder and modify virtual source path --- package.json | 20 +++++ package.nls.json | 2 + package.nls.zh-CN.json | 2 + src/EIDEProjectExplorer.ts | 170 +++++++++++++++++++++++++++++++++++-- src/EIDETypeDefine.ts | 2 + src/extension.ts | 31 +++++-- 6 files changed, 209 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 7cf2d58b..f3f7ae70 100644 --- a/package.json +++ b/package.json @@ -555,6 +555,14 @@ "command": "_cl.eide.project.source.virtual_folder_add", "title": "%eide.explorer.add.folder%" }, + { + "command": "_cl.eide.project.source.file.show.dir", + "title": "%eide.explorer.show.file.dir%" + }, + { + "command": "_cl.eide.project.source.modify.path", + "title": "%eide.explorer.modify.file.path%" + }, { "command": "_cl.eide.project.source.virtual_folder_remove", "title": "%eide.explorer.remove.folder%" @@ -1054,6 +1062,14 @@ "command": "_cl.eide.project.source.virtual_file_remove", "when": "viewItem == V_FILE_ITEM || viewItem == V_EXCFILE_ITEM && view == Project" }, + { + "command": "_cl.eide.project.source.file.show.dir", + "when": "viewItem == FILE_ITEM || viewItem == EXCFILE_ITEM || viewItem == V_FILE_ITEM || viewItem == V_EXCFILE_ITEM && view == Project" + }, + { + "command": "_cl.eide.project.source.modify.path", + "when": "viewItem == V_FOLDER || viewItem == V_FOLDER_ROOT || viewItem == V_FILE_ITEM || viewItem == V_EXCFILE_ITEM && view == Project" + }, { "command": "_cl.eide.project.addPackage", "group": "inline", @@ -1207,6 +1223,10 @@ "group": "inline", "when": "viewItem == DEPENDENCE && view == Project" }, + { + "command": "_cl.eide.project.modify.deps", + "when": "viewItem == DEPENDENCE && view == Project" + }, { "command": "_cl.eide.project.addIncludeDir", "group": "inline", diff --git a/package.nls.json b/package.nls.json index 8e0c9ba2..951ff59e 100644 --- a/package.nls.json +++ b/package.nls.json @@ -57,6 +57,8 @@ "eide.explorer.rename.folder": "Rename", "eide.explorer.exclude.folder": "Exclude Folder", "eide.explorer.include.folder": "Include Folder", + "eide.explorer.show.file.dir": "Show In File Explorer", + "eide.explorer.modify.file.path": "Modify File Path", "eide.source.show_cmsis_config_wizard": "CMSIS Configuration Wizard", "eide.source.show.disassembly": "Show Disassembly", diff --git a/package.nls.zh-CN.json b/package.nls.zh-CN.json index 51a73b2d..6906972c 100644 --- a/package.nls.zh-CN.json +++ b/package.nls.zh-CN.json @@ -50,6 +50,8 @@ "eide.explorer.rename.folder": "重命名", "eide.explorer.exclude.folder": "从项目中排除", "eide.explorer.include.folder": "取消排除", + "eide.explorer.show.file.dir": "在文件浏览器中显示", + "eide.explorer.modify.file.path": "修改源文件路径", "eide.source.show_cmsis_config_wizard": "CMSIS Configuration Wizard", "eide.source.show.disassembly": "查看反汇编", diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index 09caadfe..e3d68483 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -146,7 +146,7 @@ type GroupRegion = 'PACK' | 'Components' | 'ComponentItem'; interface TreeItemValue { key?: string; alias?: string; - value: string | File; + value: string | File; // if TreeItem refer to a file, the value type is 'File' contextVal?: string; tooltip?: string; icon?: string; @@ -451,8 +451,8 @@ interface VirtualFolderInfo { } interface VirtualFileInfo { - path: string; - vFile: VirtualFile; + path: string; // virtual path + vFile: VirtualFile; // virtual file info } class ProjectDataProvider implements vscode.TreeDataProvider { @@ -1760,8 +1760,14 @@ export class ProjectExplorer { this.cppcheck_out = vscode.window.createOutputChannel('eide-cppcheck'); // register doc event - context.subscriptions.push(vscode.workspace.onDidSaveTextDocument((doc) => this.onCustomDepYamlSaved(doc))); - context.subscriptions.push(vscode.workspace.onDidCloseTextDocument((doc) => this.onCustomDepYamlClosed(doc))); + context.subscriptions.push(vscode.workspace.onDidSaveTextDocument((doc) => { + this.onCustomDepYamlSaved(doc); + this.onFolderSourceYamlSaved(doc); + })); + context.subscriptions.push(vscode.workspace.onDidCloseTextDocument((doc) => { + this.onCustomDepYamlClosed(doc); + this.onFolderSourceYamlClosed(doc); + })); this.on('request_open_project', (fsPath: string) => this.dataProvider.OpenProject(fsPath)); this.on('request_create_project', (option: CreateOptions) => this.dataProvider.CreateProject(option)); @@ -2707,7 +2713,7 @@ export class ProjectExplorer { placeHolder: 'Input the new name', ignoreFocusOut: true, validateInput: (input) => { - if (!/^\w+$/.test(input)) { return `must match '^\\w+$'`; } + if (!this.vFolderNameMatcher.test(input)) { return `must match '${this.vFolderNameMatcher.source}'`; } return undefined; } }); @@ -3197,9 +3203,7 @@ export class ProjectExplorer { value: prjConfig.name, ignoreFocusOut: true, placeHolder: 'Input project name', - validateInput: (input: string): string | undefined => { - return input.trim() === '' ? 'project name can not be empty' : undefined; - } + validateInput: (name) => AbstractProject.validateProjectName(name) }); if (newName && newName !== prjConfig.name) { @@ -3502,9 +3506,12 @@ export class ProjectExplorer { const prj = this.dataProvider.GetProjectByIndex(item.val.projectIndex); + // if it's a virtual file, we use virtual path if (item.type === TreeItemType.V_FILE_ITEM) { prj.excludeSourceFile((item.val.obj).path); } + + // if it's a fs file, we use fs path else if (item.val.value instanceof File) { prj.excludeSourceFile(item.val.value.path); } @@ -3560,6 +3567,151 @@ export class ProjectExplorer { } } + async showFileInExplorer(item: ProjTreeItem) { + + let file: File | undefined; + + if (item.val.value instanceof File) { // if value is a file, use it + file = new File(NodePath.normalize(item.val.value.path)); + } + + if (file) { + vscode.commands.executeCommand('revealFileInOS', vscode.Uri.file(file.path)); + } + } + + // KV: + private prjFolderSourceChangesMap: Map = new Map(); + async modifySourcesPath(item: ProjTreeItem) { + + const prj = this.dataProvider.GetProjectByIndex(item.val.projectIndex); + const vSourceManager = prj.getVirtualSourceManager(); + + // virtual file + if (item.type === TreeItemType.V_FILE_ITEM || + item.type === TreeItemType.V_EXCFILE_ITEM) { + + const vInfo = item.val.obj; + const path = await vscode.window.showInputBox({ + value: vInfo.vFile.path, + ignoreFocusOut: true, + prompt: `Input a file path (allow relative path)` + }); + + if (path == undefined) { + return; + } + + const repath = prj.ToRelativePath(path) || path; + const vFileInfo = vSourceManager.getFile(vInfo.path); + if (vFileInfo) { + vFileInfo.path = repath; + vSourceManager.notifyUpdateFile(vInfo.path); + } else { + GlobalEvent.emit('msg', newMessage('Error', `Internal error: can't get obj from virtual path: '${vInfo.path}'`)); + } + } + + // virtual folder + else if (item.type === TreeItemType.V_FOLDER || + item.type === TreeItemType.V_FOLDER_ROOT) { + + const vInfo = item.val.obj; + const vFolderInfo = vSourceManager.getFolder(vInfo.path); + if (vFolderInfo) { + + const getOldFileNameByProject = (vPath: string, prj: AbstractProject) => { + for (const KV of this.prjFolderSourceChangesMap) { + if (KV[1].vFolderPath == vPath && + KV[1].project.getWsPath().toLowerCase() == prj.getWsPath().toLowerCase()) { + return KV[0]; + } + } + }; + + let tmpFile: File; + + let oldName = getOldFileNameByProject(vInfo.path, prj); + if (oldName) { + tmpFile = File.fromArray([os.tmpdir(), oldName]); + } else { // if file not exist, add to mapper + tmpFile = File.fromArray([os.tmpdir(), `eide-vfolder-${Date.now()}.yaml`]); + this.prjFolderSourceChangesMap.set(tmpFile.name, { vFolderPath: vInfo.path, project: prj }); + } + + const yamlLines: string[] = [ + `#`, + `# You can modify files path by editing and saving this file (allow relative path).`, + `#`, + ``, + yml.stringify(vFolderInfo.files, { indent: 4 }) + ]; + + tmpFile.Write(yamlLines.join(os.EOL)); + vscode.window.showTextDocument(vscode.Uri.file(tmpFile.path), { preview: false }); + + } else { + GlobalEvent.emit('msg', newMessage('Error', `Internal error: can't get obj from virtual path: '${vInfo.path}'`)); + } + } + } + + // callbk, if config file saved, apply the changes + private onFolderSourceYamlSaved(doc: vscode.TextDocument) { + + const tmpFileName = NodePath.basename(doc.fileName); + const info = this.prjFolderSourceChangesMap.get(tmpFileName); + + // skip irrelevant files + if (info == undefined) return; + + // save to config + try { + + const vSrcManger = info.project.getVirtualSourceManager(); + const vFolderInfo = vSrcManger.getFolder(info.vFolderPath); + if (!vFolderInfo) { + throw new Error(`Virtual folder '${info.vFolderPath}' is not exist !`); + } + + let fileList: VirtualFile[] = yml.parse(doc.getText()); + if (fileList != undefined && !Array.isArray(fileList)) { + throw new Error(`Type error, files list must be an array, please check your yaml config file !`); + } + + // convert to repath + if (fileList) { + fileList = fileList.map((vFile) => { + return { + path: info.project.ToRelativePath(vFile.path) || vFile.path + }; + }); + } + + vFolderInfo.files = fileList || []; + vSrcManger.notifyUpdateFolder(info.vFolderPath); + + } catch (error) { + GlobalEvent.emit('msg', ExceptionToMessage(error, 'Warning')); + } + } + + // callbk, if config file closed, rm tmp file + private onFolderSourceYamlClosed(doc: vscode.TextDocument) { + + // skip irrelevant files + const tmpFileName = NodePath.basename(doc.fileName); + if (!this.prjFolderSourceChangesMap.has(tmpFileName)) return; + + // do + try { + this.prjFolderSourceChangesMap.delete(tmpFileName); // remove from mapper + fs.unlinkSync(`${os.tmpdir()}/${tmpFileName}`); + } catch (error) { + GlobalEvent.emit('msg', ExceptionToMessage(error, 'Hidden')); + } + } + CopyItemValue(item: ProjTreeItem) { if (item.val.value instanceof File) { vscode.env.clipboard.writeText(item.val.value.path); diff --git a/src/EIDETypeDefine.ts b/src/EIDETypeDefine.ts index c6c980f8..7570640d 100644 --- a/src/EIDETypeDefine.ts +++ b/src/EIDETypeDefine.ts @@ -432,6 +432,8 @@ export interface ProjectTargetInfo { } export interface VirtualFile { + // this must be an relative path + // because virtual file path may be outside the project root directory path: string; } diff --git a/src/extension.ts b/src/extension.ts index 08dd6472..2eefc8ec 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -80,6 +80,7 @@ export async function activate(context: vscode.ExtensionContext) { subscriptions.push(vscode.commands.registerCommand('eide.ReloadStm8Devs', () => reloadStm8Devices())); subscriptions.push(vscode.commands.registerCommand('eide.selectBaudrate', () => onSelectSerialBaudrate())); + // operations const operationExplorer = new OperationExplorer(context); subscriptions.push(vscode.commands.registerCommand('_cl.eide.Operation.Open', () => operationExplorer.OnOpenProject())); subscriptions.push(vscode.commands.registerCommand('_cl.eide.Operation.Create', () => operationExplorer.OnCreateProject())); @@ -88,30 +89,32 @@ export async function activate(context: vscode.ExtensionContext) { subscriptions.push(vscode.commands.registerCommand('_cl.eide.Operation.OpenSerialPortMonitor', () => operationExplorer.onOpenSerialPortMonitor())); subscriptions.push(vscode.commands.registerCommand('_cl.eide.Operation.openSettings', () => SettingManager.jumpToSettings('@ext:cl.eide'))); - // public cmds + // operations user cmds subscriptions.push(vscode.commands.registerCommand('eide.operation.install_toolchain', () => operationExplorer.OnSetToolchainPath())); subscriptions.push(vscode.commands.registerCommand('eide.operation.import_project', () => operationExplorer.OnImportProject())); subscriptions.push(vscode.commands.registerCommand('eide.operation.new_project', () => operationExplorer.OnCreateProject())); + // projects projectExplorer = new ProjectExplorer(context); - subscriptions.push(vscode.commands.registerCommand('_cl.eide.workspace.build', () => projectExplorer.buildWorkspace())); subscriptions.push(vscode.commands.registerCommand('_cl.eide.workspace.rebuild', () => projectExplorer.buildWorkspace(true))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.workspace.open.config', () => projectExplorer.openWorkspaceConfig())); subscriptions.push(vscode.commands.registerCommand('_cl.eide.workspace.make.template', (item) => projectExplorer.ExportToTemplate(undefined, true))); - // public cmds + // project user cmds subscriptions.push(vscode.commands.registerCommand('eide.project.rebuild', (item) => projectExplorer.BuildSolution(item))); subscriptions.push(vscode.commands.registerCommand('eide.project.build', (item) => projectExplorer.BuildSolution(item, { useFastMode: true }))); subscriptions.push(vscode.commands.registerCommand('eide.project.clean', (item) => projectExplorer.BuildClean(item))); subscriptions.push(vscode.commands.registerCommand('eide.project.uploadToDevice', (item) => projectExplorer.UploadToDevice(item))); subscriptions.push(vscode.commands.registerCommand('eide.reinstall.binaries', () => checkAndInstallBinaries(context, true))); + // operations bar subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.historyRecord', () => projectExplorer.openHistoryRecords())); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.clearHistoryRecord', () => projectExplorer.clearAllHistoryRecords())); + + // project subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.showBuildParams', (item) => projectExplorer.BuildSolution(item, { useDebug: true }))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.generate.makefile', (item) => projectExplorer.generateMakefile(item))); - subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.setActive', (item) => projectExplorer.setActiveProject(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.close', (item) => projectExplorer.Close(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.saveAll', () => projectExplorer.SaveAll())); @@ -119,59 +122,69 @@ export async function activate(context: vscode.ExtensionContext) { subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.switchMode', (item) => projectExplorer.switchTarget(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.exportAsTemplate', (item) => projectExplorer.ExportToTemplate(item))); + // project explorer subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.addSrcDir', (item) => projectExplorer.AddSrcDir(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.removeSrcDir', (item) => projectExplorer.RemoveSrcDir(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.sourceRoot.refresh', (item) => projectExplorer.refreshSrcRoot(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.modify.files.options', (item) => projectExplorer.showFilesOptions(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.import.ext.source.struct', (item) => projectExplorer.ImportSourceFromExtProject(item))); + // filesystem files subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.filesystem_folder_add_file', (item) => projectExplorer.fs_folderAddFile(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.filesystem_folder_add', (item) => projectExplorer.fs_folderAdd(item))); + // virtual files subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.virtual_folder_add_file', (item) => projectExplorer.Virtual_folderAddFile(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.virtual_folder_add', (item) => projectExplorer.Virtual_folderAdd(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.virtual_folder_remove', (item) => projectExplorer.Virtual_removeFolder(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.virtual_folder_rename', (item) => projectExplorer.Virtual_renameFolder(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.virtual_file_remove', (item) => projectExplorer.Virtual_removeFile(item))); + // file other operations subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.excludeSource', (item) => projectExplorer.ExcludeSourceFile(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.unexcludeSource', (item) => projectExplorer.UnexcludeSourceFile(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.excludeFolder', (item) => projectExplorer.ExcludeFolder(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.unexcludeFolder', (item) => projectExplorer.UnexcludeFolder(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.file.show.dir', (item) => projectExplorer.showFileInExplorer(item))); + subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.modify.path', (item) => projectExplorer.modifySourcesPath(item))); + // package subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.installCMSISHeaders', (item) => projectExplorer.installCMSISHeaders(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.removePackage', (item) => projectExplorer.UninstallKeilPackage(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.addPackage', (item) => projectExplorer.InstallKeilPackage(item.val.projectIndex))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.exportXml', (item) => projectExplorer.ExportKeilXml(item.val.projectIndex))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.setDevice', (item) => projectExplorer.SetDevice(item.val.projectIndex))); + + // builder subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.modifyCompileConfig', (item) => projectExplorer.ModifyCompileConfig(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.switchToolchain', (item) => projectExplorer.onSwitchCompileTools(item))); + // flasher subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.modifyUploadConfig', (item) => projectExplorer.ModifyUploadConfig(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.switchUploader', (item) => projectExplorer.switchUploader(item))); + // project deps subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.addIncludeDir', (item) => projectExplorer.AddIncludeDir(item.val.projectIndex))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.addDefine', (item) => projectExplorer.AddDefine(item.val.projectIndex))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.addLibDir', (item) => projectExplorer.AddLibDir(item.val.projectIndex))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.showIncludeDir', (item) => projectExplorer.showIncludeDir(item.val.projectIndex))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.showDefine', (item) => projectExplorer.showDefine(item.val.projectIndex))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.showLibDir', (item) => projectExplorer.showLibDir(item.val.projectIndex))); - subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.modifyOtherSettings', (item) => projectExplorer.ModifyOtherSettings(item))); - subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.import.ext.source.struct', (item) => projectExplorer.ImportSourceFromExtProject(item))); - subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.modify.deps', (item) => projectExplorer.ModifyCustomDependence(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.removeDependenceItem', (item) => projectExplorer.RemoveDependenceItem(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.importDependenceFromPack', (item) => projectExplorer.ImportPackageDependence(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.removeDependenceFromPack', (item) => projectExplorer.RemovePackageDependence(item))); + // tree view global subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.copyItemValue', (item) => projectExplorer.CopyItemValue(item))); - /* other project tools */ + // other project tools subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.show_disassembly', (url) => projectExplorer.showDisassembly(url))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.show_cmsis_config_wizard', (url) => projectExplorer.showCmsisConfigWizard(url))); - //subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.cppcheck.check_file', (url) => projectExplorer.cppcheckFile(url))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.cppcheck.check_all', (item) => projectExplorer.cppcheckProject(item))); subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.cppcheck.clear_all', (item) => projectExplorer.clearCppcheckDiagnostic())); + //subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.cppcheck.check_file', (url) => projectExplorer.cppcheckFile(url))); operationExplorer.on('request_open_project', (fsPath) => projectExplorer.emit('request_open_project', fsPath)); operationExplorer.on('request_create_project', (option) => projectExplorer.emit('request_create_project', option)); From 13cf5804b00dead5f9c33ba8b6cf4a6076020b5b Mon Sep 17 00:00:00 2001 From: null Date: Sat, 4 Dec 2021 02:31:27 +0800 Subject: [PATCH 37/48] validate project name when change it --- src/EIDEProject.ts | 16 +++++++++++++++- src/OperationExplorer.ts | 18 ++++-------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/EIDEProject.ts b/src/EIDEProject.ts index 1c967afa..410c245f 100644 --- a/src/EIDEProject.ts +++ b/src/EIDEProject.ts @@ -54,7 +54,10 @@ import { DeleteDir } from './Platform'; import { IDebugConfigGenerator } from './DebugConfigGenerator'; import { md5, copyObject } from './utility'; import { ResInstaller } from './ResInstaller'; -import { view_str$prompt$not_found_compiler } from './StringTable'; +import { + view_str$prompt$not_found_compiler, view_str$operation$name_can_not_be_blank, + view_str$operation$name_can_not_have_invalid_char +} from './StringTable'; import { SettingManager } from './SettingManager'; export class CheckError extends Error { @@ -728,6 +731,17 @@ export abstract class AbstractProject { return (grp).dir == undefined; } + static validateProjectName(value: string): string | undefined { + + if (value.trim() === '') { + return view_str$operation$name_can_not_be_blank; + } + + if (/&|<|>|\(|\)|@|\^|\|/.test(value)) { + return view_str$operation$name_can_not_have_invalid_char; + } + } + private loadProjectDirectory() { // load root folder diff --git a/src/OperationExplorer.ts b/src/OperationExplorer.ts index a621a653..510abf77 100644 --- a/src/OperationExplorer.ts +++ b/src/OperationExplorer.ts @@ -60,6 +60,7 @@ import * as vscode from 'vscode'; import * as NodePath from 'path'; import { append2SysEnv } from './Platform'; import { ResInstaller } from './ResInstaller'; +import { AbstractProject } from './EIDEProject'; interface TemplatePickItem extends vscode.QuickPickItem, TemplateInfo { cacheFileName: string | undefined; @@ -290,17 +291,6 @@ export class OperationExplorer { this.provider.Update(); } - private validateProjectName(value: string): string | undefined { - - if (value.trim() === '') { - return view_str$operation$name_can_not_be_blank; - } - - if (/&|<|>|\(|\)|@|\^|\|/.test(value)) { - return view_str$operation$name_can_not_have_invalid_char; - } - } - //--------------- event ----------------- OnOpenProject() { @@ -458,7 +448,7 @@ export class OperationExplorer { const name = await vscode.window.showInputBox({ placeHolder: input_project_name, ignoreFocusOut: true, - validateInput: (name) => this.validateProjectName(name) + validateInput: (name) => AbstractProject.validateProjectName(name) }); if (name === undefined) { return; @@ -1092,7 +1082,7 @@ export class OperationExplorer { const name = await vscode.window.showInputBox({ placeHolder: input_project_name, ignoreFocusOut: true, - validateInput: (name) => this.validateProjectName(name) + validateInput: (name) => AbstractProject.validateProjectName(name) }); if (name === undefined) { @@ -1165,7 +1155,7 @@ export class OperationExplorer { const name = await vscode.window.showInputBox({ placeHolder: input_project_name, ignoreFocusOut: true, - validateInput: (name) => this.validateProjectName(name) + validateInput: (name) => AbstractProject.validateProjectName(name) }); if (name === undefined) { From d1cd8b72f2961027365202a7d031f14f33ce6bdb Mon Sep 17 00:00:00 2001 From: null Date: Sat, 4 Dec 2021 16:19:47 +0800 Subject: [PATCH 38/48] support show output files --- package.json | 10 +- package.nls.json | 1 + package.nls.zh-CN.json | 1 + res/icon/Report_16x.svg | 1 + res/icon/folder_type_binary.svg | 1 + src/EIDEProject.ts | 3 +- src/EIDEProjectExplorer.ts | 161 ++++++++++++++++++++++++++------ src/SettingManager.ts | 6 +- src/extension.ts | 2 +- 9 files changed, 150 insertions(+), 36 deletions(-) create mode 100644 res/icon/Report_16x.svg create mode 100644 res/icon/folder_type_binary.svg diff --git a/package.json b/package.json index f3f7ae70..58df23f3 100644 --- a/package.json +++ b/package.json @@ -143,6 +143,12 @@ { "title": "Embedded IDE", "properties": { + "EIDE.Option.ShowOutputFilesInExplorer": { + "type": "boolean", + "scope": "resource", + "markdownDescription": "%settings.option.show.output.files%", + "default": true + }, "EIDE.Option.MapViewParserDepth": { "type": "integer", "scope": "resource", @@ -1064,7 +1070,7 @@ }, { "command": "_cl.eide.project.source.file.show.dir", - "when": "viewItem == FILE_ITEM || viewItem == EXCFILE_ITEM || viewItem == V_FILE_ITEM || viewItem == V_EXCFILE_ITEM && view == Project" + "when": "viewItem == OUTPUT_FILE_ITEM || viewItem == FILE_ITEM || viewItem == EXCFILE_ITEM || viewItem == V_FILE_ITEM || viewItem == V_EXCFILE_ITEM && view == Project" }, { "command": "_cl.eide.project.source.modify.path", @@ -1186,7 +1192,7 @@ { "command": "_cl.eide.project.sourceRoot.refresh", "group": "inline", - "when": "viewItem == FOLDER_ROOT_DEPS || viewItem == FOLDER_ROOT || viewItem == V_FOLDER_ROOT && view == Project" + "when": "viewItem == OUTPUT_FOLDER || viewItem == FOLDER_ROOT_DEPS || viewItem == FOLDER_ROOT || viewItem == V_FOLDER_ROOT && view == Project" }, { "command": "_cl.eide.project.removeSrcDir", diff --git a/package.nls.json b/package.nls.json index 951ff59e..64661f22 100644 --- a/package.nls.json +++ b/package.nls.json @@ -93,6 +93,7 @@ "settings.option.insert.extcommands.at.begin": "The built-in command lines will insert at the beginning of the `beforeBuildTasks / afterBuildTasks`", "settings.option.show.source.references": "Show c/c++ header references for source file", "settings.option.mapView.parser.depth": "The depth limit of the obj file path when *.map.view is displayed. Obj files larger than this depth are ignored.", + "settings.option.show.output.files": "Show output files in project resource explorer", "settings.repo.use.proxy": "Use proxy to improve network speed for github (experimental function)", "settings.template.repo.url": "Public github template repository url, format: ``/``/contents/``", diff --git a/package.nls.zh-CN.json b/package.nls.zh-CN.json index 6906972c..759864bf 100644 --- a/package.nls.zh-CN.json +++ b/package.nls.zh-CN.json @@ -125,6 +125,7 @@ "settings.option.disable.explorer_context.menu": "禁用资源浏览器上下文菜单", "settings.option.show.source.references": "显示源文件的头文件引用", "settings.option.mapView.parser.depth": "显示 *.map.view 时,obj 文件路径的深度限制。大于该深度的 obj 文件将被忽略", + "settings.option.show.output.files": "在项目资源管理器中显示编译输出文件", "string.eide.startup.walkthroughs": "Embedded IDE 演示", "string.eide.startup.walkthroughs.detail": "我们将向您展示如何开始使用 Embedded IDE 。", diff --git a/res/icon/Report_16x.svg b/res/icon/Report_16x.svg new file mode 100644 index 00000000..d29e5f5f --- /dev/null +++ b/res/icon/Report_16x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/res/icon/folder_type_binary.svg b/res/icon/folder_type_binary.svg new file mode 100644 index 00000000..d19e36c0 --- /dev/null +++ b/res/icon/folder_type_binary.svg @@ -0,0 +1 @@ +folder_type_binary \ No newline at end of file diff --git a/src/EIDEProject.ts b/src/EIDEProject.ts index 410c245f..b0b557b6 100644 --- a/src/EIDEProject.ts +++ b/src/EIDEProject.ts @@ -672,8 +672,9 @@ export abstract class AbstractProject { static readonly libFileFilter: RegExp[] = [/\.lib$/i, /\.a$/i, /\.o$/i, /\.obj$/i]; static readonly asmfileFilter: RegExp[] = [/\.s$/i, /\.a51$/i, /\.asm$/i]; - static readonly excludeDirFilter: RegExp[] = [/^\.git$/i, /^\.vs$/i, /^\.vscode$/i, /^\.eide$/i]; + static readonly buildOutputMatcher: RegExp = /\.(?:elf|axf|out|hex|bin|s19|map|map\.view)$/i; + static readonly excludeDirFilter: RegExp[] = [/^\.git$/i, /^\.vs$/i, /^\.vscode$/i, /^\.eide$/i]; // this folder list will be excluded when search include path static readonly excludeIncSearchList: string[] = [DependenceManager.DEPENDENCE_DIR]; diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index e3d68483..5623fbae 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -137,6 +137,10 @@ enum TreeItemType { // source refs SRCREF_FILE_ITEM, + // output + OUTPUT_FOLDER, + OUTPUT_FILE_ITEM, + ACTIVED_ITEM, ACTIVED_GROUP } @@ -304,11 +308,14 @@ export class ProjTreeItem extends vscode.TreeItem { } } - private getSourceFileIconName(suffix: string): string | undefined { + private getSourceFileIconName(fileName_: string, suffix_: string): string | undefined { let name: string | undefined; - switch (suffix.toLowerCase()) { + const fileName = fileName_.toLowerCase(); + const suffix = suffix_.toLowerCase(); + + switch (suffix) { case '.c': name = 'file_type_c.svg'; break; @@ -337,10 +344,22 @@ export class ProjTreeItem extends vscode.TreeItem { break; case '.o': case '.obj': + case '.axf': + case '.elf': + case '.bin': + case '.out': name = 'file_type_binary.svg'; break; + case '.map': + name = 'file_type_map.svg'; + break; + // other suffix default: - name = 'document-light.svg'; + if (fileName.endsWith('.map.view')) { + name = 'Report_16x.svg'; + } else { + name = 'document-light.svg'; + } break; } @@ -413,6 +432,9 @@ export class ProjTreeItem extends vscode.TreeItem { case TreeItemType.ACTIVED_GROUP: name = 'TestCoveredPassing_16x.svg';//'RecursivelyCheckAll_16x.svg'; break; + case TreeItemType.OUTPUT_FOLDER: + name = 'folder_type_binary.svg'; + break; default: { // if it's a source file, get icon @@ -420,7 +442,7 @@ export class ProjTreeItem extends vscode.TreeItem { const file: File = this.val.value; // if file is existed, get icon by suffix if (file.IsFile()) { - name = this.getSourceFileIconName(file.suffix); + name = this.getSourceFileIconName(file.name, file.suffix); } // if file not existed, show warning icon else { @@ -455,6 +477,46 @@ interface VirtualFileInfo { vFile: VirtualFile; // virtual file info } +class ProjectItemCache { + + // + private itemCache: Map = new Map(); + + getTreeItem(prj: AbstractProject, itemType: TreeItemType): ProjTreeItem | undefined { + const cache = this.itemCache.get(prj.getWsPath()); + if (cache) { + return cache[TreeItemType[itemType]]; + } + } + + setTreeItem(prj: AbstractProject, item: ProjTreeItem, isRoot?: boolean) { + const cache = this.itemCache.get(prj.getWsPath()); + if (cache) { + if (isRoot) { + cache.root = item; + } else { + cache[TreeItemType[item.type]] = item; + } + } else if (isRoot) { // if not found and type is root, set it + this.itemCache.set(prj.getWsPath(), { root: item }); + } + } + + delTreeItem(prj: AbstractProject, itemType?: TreeItemType): ProjTreeItem | undefined { + const cache = this.itemCache.get(prj.getWsPath()); + if (cache) { + if (itemType) { + const key = TreeItemType[itemType]; + const deleted = cache[key]; + cache[key] = undefined; // del item + return deleted; + } else { // del all + this.itemCache.delete(prj.getWsPath()); + } + } + } +} + class ProjectDataProvider implements vscode.TreeDataProvider { private static readonly recName = 'sln.record'; @@ -465,7 +527,9 @@ class ProjectDataProvider implements vscode.TreeDataProvider { private recFile: File; private context: vscode.ExtensionContext; private activePrjPath: string | undefined; - private itemCache: Map = new Map(); + + // project tree item refresh cache + treeCache: ProjectItemCache = new ProjectItemCache(); onDidChangeTreeData?: vscode.Event | undefined; dataChangedEvent: vscode.EventEmitter; @@ -489,30 +553,23 @@ class ProjectDataProvider implements vscode.TreeDataProvider { this.LoadWorkspaceProject(); } - getCacheItem(prj: AbstractProject, itemType: TreeItemType): ProjTreeItem | undefined { - const cache = this.itemCache.get(prj.getWsPath()); - if (cache) { - return cache[TreeItemType[itemType]]; - } - } - onProjectChanged(prj: AbstractProject, type?: DataChangeType) { switch (type) { case 'files': - this.UpdateView(this.getCacheItem(prj, TreeItemType.PROJECT)); + this.UpdateView(this.treeCache.getTreeItem(prj, TreeItemType.PROJECT)); break; case 'compiler': - this.UpdateView(this.getCacheItem(prj, TreeItemType.COMPILE_CONFIGURATION)); + this.UpdateView(this.treeCache.getTreeItem(prj, TreeItemType.COMPILE_CONFIGURATION)); break; case 'uploader': - this.UpdateView(this.getCacheItem(prj, TreeItemType.UPLOAD_OPTION)); + this.UpdateView(this.treeCache.getTreeItem(prj, TreeItemType.UPLOAD_OPTION)); break; case 'pack': - this.UpdateView(this.getCacheItem(prj, TreeItemType.PACK)); + this.UpdateView(this.treeCache.getTreeItem(prj, TreeItemType.PACK)); break; case 'dependence': - this.UpdateView(this.getCacheItem(prj, TreeItemType.PACK)); - this.UpdateView(this.getCacheItem(prj, TreeItemType.DEPENDENCE)); + this.UpdateView(this.treeCache.getTreeItem(prj, TreeItemType.PACK)); + this.UpdateView(this.treeCache.getTreeItem(prj, TreeItemType.DEPENDENCE)); break; default: this.UpdateView(); @@ -653,13 +710,8 @@ class ProjectDataProvider implements vscode.TreeDataProvider { }); iList.push(cItem); - // cache item - const oldItem = this.itemCache.get(sln.getWsPath()); - if (oldItem) { - oldItem.root = cItem; - } else { - this.itemCache.set(sln.getWsPath(), { root: cItem }); - } + // cache project root item + this.treeCache.setTreeItem(sln, cItem, true); }); } else { @@ -711,10 +763,9 @@ class ProjectDataProvider implements vscode.TreeDataProvider { })); // cache sub root view - const iCache = this.itemCache.get(project.getWsPath()); - if (iCache) { - iList.forEach((item) => { iCache[TreeItemType[item.type]] = item; }); - } + iList.forEach((item) => { + this.treeCache.setTreeItem(project, item); + }); } break; case TreeItemType.PROJECT: @@ -770,6 +821,21 @@ class ProjectDataProvider implements vscode.TreeDataProvider { tooltip: isFileExcluded ? view_str$project$excludeFile : file.path, })); }); + + // show output files + if (SettingManager.GetInstance().isShowOutputFilesInExplorer()) { + const label = `Output Files`; + const tItem = new ProjTreeItem(TreeItemType.OUTPUT_FOLDER, { + value: label, + collapsibleState: vscode.TreeItemCollapsibleState.Collapsed, + projectIndex: element.val.projectIndex, + tooltip: label, + }); + iList.push(tItem); + this.treeCache.setTreeItem(project, tItem); + } else { + this.treeCache.delTreeItem(project, TreeItemType.OUTPUT_FOLDER); + } } break; case TreeItemType.PACK: @@ -1012,6 +1078,24 @@ class ProjectDataProvider implements vscode.TreeDataProvider { } } break; + // output folder + case TreeItemType.OUTPUT_FOLDER: + { + const outFolder = project.getOutputFolder(); + const fList = outFolder.GetList([AbstractProject.buildOutputMatcher], File.EMPTY_FILTER); + fList.forEach((file) => { + iList.push(new ProjTreeItem(TreeItemType.OUTPUT_FILE_ITEM, { + value: file, + collapsibleState: vscode.TreeItemCollapsibleState.None, + projectIndex: element.val.projectIndex, + tooltip: file.path, + })); + }); + } + break; + // output file item + case TreeItemType.OUTPUT_FILE_ITEM: + break; case TreeItemType.COMPONENT_GROUP: case TreeItemType.ACTIVED_GROUP: case TreeItemType.PACK_GROUP: @@ -1957,6 +2041,13 @@ export class ProjectExplorer { this.dataProvider.clearAllRecords(); } + notifyUpdateOutputFolder(prj: AbstractProject) { + const item = this.dataProvider.treeCache.getTreeItem(prj, TreeItemType.OUTPUT_FOLDER); + if (item) { + this.dataProvider.UpdateView(item); + } + } + private _buildLock: boolean = false; BuildSolution(prjItem?: ProjTreeItem, options?: BuildOptions) { @@ -1982,7 +2073,12 @@ export class ProjectExplorer { // set event handler const toolchain = prj.getToolchain().name; - codeBuilder.on('finished', () => prj.notifyUpdateSourceRefs(toolchain)); + + // notify view update after build done ! + codeBuilder.on('finished', () => { + prj.notifyUpdateSourceRefs(toolchain); + this.notifyUpdateOutputFolder(prj); + }); // start build codeBuilder.build(options); @@ -2630,6 +2726,9 @@ export class ProjectExplorer { const prj = this.dataProvider.GetProjectByIndex(item.val.projectIndex); switch (item.type) { + case TreeItemType.OUTPUT_FOLDER: + this.notifyUpdateOutputFolder(prj); + break; case TreeItemType.V_FOLDER_ROOT: prj.refreshSourceRoot((item.val.obj).path); break; @@ -3163,7 +3262,7 @@ export class ProjectExplorer { } private updateSettingsView(prj: AbstractProject) { - this.dataProvider.UpdateView(this.dataProvider.getCacheItem(prj, TreeItemType.SETTINGS)); + this.dataProvider.UpdateView(this.dataProvider.treeCache.getTreeItem(prj, TreeItemType.SETTINGS)); } async ModifyOtherSettings(item: ProjTreeItem) { diff --git a/src/SettingManager.ts b/src/SettingManager.ts index ae2c31b5..93ac3c99 100644 --- a/src/SettingManager.ts +++ b/src/SettingManager.ts @@ -242,12 +242,16 @@ export class SettingManager { //--------------------- Global Option ------------------------ + isShowOutputFilesInExplorer(): boolean { + return this.getConfiguration().get('Option.ShowOutputFilesInExplorer') || false; + } + getBuilderAdditionalCommandLine(): string | undefined { return this.getConfiguration().get('Builder.AdditionalCommandLine'); } getMapViewParserDepth(): number { - return this.getConfiguration().get('Option.MapViewParserDepth') || 3; + return this.getConfiguration().get('Option.MapViewParserDepth') || 1; } isDisplaySourceRefs(): boolean { diff --git a/src/extension.ts b/src/extension.ts index 2eefc8ec..46d5ba0f 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -577,7 +577,7 @@ class MapViewEditorProvider implements vscode.CustomTextEditorProvider { // init webviewPanel.title = title; - webviewPanel.iconPath = vscode.Uri.parse(ResManager.GetInstance().GetIconByName('file_type_map.svg').ToUri()); + webviewPanel.iconPath = vscode.Uri.file(ResManager.GetInstance().GetIconByName('Report_16x.svg').path); webviewPanel.webview.html = this.genHtmlCont(title, 'No Content'); webviewPanel.onDidDispose(() => this.deleteRef(viewFile.path, uid)); From 0cfd077b99d0e42842999e1ce0b7271211d66f54 Mon Sep 17 00:00:00 2001 From: null Date: Sat, 4 Dec 2021 18:16:39 +0800 Subject: [PATCH 39/48] support show axf/elf file info --- lang/axf.info.language-configuration.json | 9 ++++ lang/axf.info.tmLanguage.json | 59 +++++++++++++++++++++ lang/elf.info.language-configuration.json | 9 ++++ lang/elf.info.tmLanguage.json | 48 +++++++++++++++++ package.json | 36 +++++++++++++ src/EIDEProjectExplorer.ts | 63 +++++++++++++++++++++++ 6 files changed, 224 insertions(+) create mode 100644 lang/axf.info.language-configuration.json create mode 100644 lang/axf.info.tmLanguage.json create mode 100644 lang/elf.info.language-configuration.json create mode 100644 lang/elf.info.tmLanguage.json diff --git a/lang/axf.info.language-configuration.json b/lang/axf.info.language-configuration.json new file mode 100644 index 00000000..026b8baa --- /dev/null +++ b/lang/axf.info.language-configuration.json @@ -0,0 +1,9 @@ +{ + "comments": { + "lineComment": ";" + }, + "indentationRules": { + "increaseIndentPattern": "^[a-zA-Z_]\\w*\\s*:\\s*", + "decreaseIndentPattern": "^[a-zA-Z_]\\w*\\s*:\\s*" + } +} \ No newline at end of file diff --git a/lang/axf.info.tmLanguage.json b/lang/axf.info.tmLanguage.json new file mode 100644 index 00000000..28151d6c --- /dev/null +++ b/lang/axf.info.tmLanguage.json @@ -0,0 +1,59 @@ +{ + "information_for_contributors": [ + "armcc axf information" + ], + "version": "1.0.0", + "name": "axf.info", + "scopeName": "source.axf.info", + "patterns": [ + { + "include": "#elf_header" + }, + { + "include": "#keyword" + }, + { + "include": "#number" + }, + { + "include": "#string" + } + ], + "repository": { + "elf_header": { + "match": "^\\s*([\\w\\/][\\w\\/\\s]+):", + "captures": { + "1": { + "name": "entity.name.type" + } + } + }, + "keyword": { + "match": "\\(([A-Z_]+)\\)|(SHF_[\\w]+|PF_[\\w]+)", + "captures": { + "1": { + "name": "keyword.control.import" + }, + "2": { + "name": "keyword.control.import" + } + } + }, + "number": { + "match": "\\b([0-9a-f]+H|0x[0-9a-f]+|[0-9a-f]+)\\b", + "captures": { + "1": { + "name": "constant.numeric" + } + } + }, + "string": { + "match": "(\"[^\"]*\"|'[^']*')", + "captures": { + "1": { + "name": "string" + } + } + } + } +} \ No newline at end of file diff --git a/lang/elf.info.language-configuration.json b/lang/elf.info.language-configuration.json new file mode 100644 index 00000000..026b8baa --- /dev/null +++ b/lang/elf.info.language-configuration.json @@ -0,0 +1,9 @@ +{ + "comments": { + "lineComment": ";" + }, + "indentationRules": { + "increaseIndentPattern": "^[a-zA-Z_]\\w*\\s*:\\s*", + "decreaseIndentPattern": "^[a-zA-Z_]\\w*\\s*:\\s*" + } +} \ No newline at end of file diff --git a/lang/elf.info.tmLanguage.json b/lang/elf.info.tmLanguage.json new file mode 100644 index 00000000..5d5f6b32 --- /dev/null +++ b/lang/elf.info.tmLanguage.json @@ -0,0 +1,48 @@ +{ + "information_for_contributors": [ + "gnu elf information" + ], + "version": "1.0.0", + "name": "elf.info", + "scopeName": "source.elf.info", + "patterns": [ + { + "include": "#elf_header" + }, + { + "include": "#number" + }, + { + "include": "#string" + } + ], + "repository": { + "elf_header": { + "match": "^\\s*([\\w\\/][\\w\\/\\s]+):\\s+(.*)", + "captures": { + "1": { + "name": "entity.name.type" + }, + "2": { + "name": "string" + } + } + }, + "number": { + "match": "\\b([0-9a-f]+H|0x[0-9a-f]+|[0-9a-f]+)\\b", + "captures": { + "1": { + "name": "constant.numeric" + } + } + }, + "string": { + "match": "(\"[^\"]*\"|'[^']*')", + "captures": { + "1": { + "name": "string" + } + } + } + } +} \ No newline at end of file diff --git a/package.json b/package.json index 58df23f3..59fc535d 100644 --- a/package.json +++ b/package.json @@ -1326,6 +1326,32 @@ "**/*.edasm" ], "configuration": "./lang/edasm.language-configuration.json" + }, + { + "id": "axf.info", + "aliases": [ + "Armcc Axf Info" + ], + "extensions": [ + ".axf.info" + ], + "filenamePatterns": [ + "**/*.axf.info" + ], + "configuration": "./lang/axf.info.language-configuration.json" + }, + { + "id": "elf.info", + "aliases": [ + "Gnu Elf Info" + ], + "extensions": [ + ".elf.info" + ], + "filenamePatterns": [ + "**/*.elf.info" + ], + "configuration": "./lang/elf.info.language-configuration.json" } ], "jsonValidation": [ @@ -1381,6 +1407,16 @@ "language": "edasm", "scopeName": "source.dasm.gcc", "path": "./lang/edasm.tmLanguage.json" + }, + { + "language": "axf.info", + "scopeName": "source.axf.info", + "path": "./lang/axf.info.tmLanguage.json" + }, + { + "language": "elf.info", + "scopeName": "source.elf.info", + "path": "./lang/elf.info.tmLanguage.json" } ], "problemMatchers": [ diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index 5623fbae..61647807 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -4088,12 +4088,75 @@ export class ProjectExplorer { }; try { + + // try to show it by eide, if failed, show it + // by vscode default api + if (this.showBinaryFiles(file, isPreview)) return; + /* We need use 'vscode.open' command, not 'showTextDocument' API, * because API can't open bin file */ vscode.commands.executeCommand('vscode.open', vsUri, { preview: isPreview }); + } catch (error) { GlobalEvent.emit('msg', ExceptionToMessage(error, 'Warning')); } } } + + private showBinaryFiles(binFile: File, isPreview?: boolean): boolean | undefined { + + try { + + const suffix = binFile.suffix.toLowerCase(); + + // show armcc axf file + if (suffix == '.axf') { + + const fromelf = File.fromArray([ + SettingManager.GetInstance().getArmcc5Dir().path, 'bin', 'fromelf.exe' + ]); + + if (!fromelf.IsFile()) return; + + const cont = child_process + .execFileSync(fromelf.path, ['--text', '-e', binFile.path]) + .toString(); + + const vDoc = VirtualDocument.instance(); + const docName = `${binFile.path}.info`; + vDoc.updateDocument(docName, cont); + + const uri = vscode.Uri.parse(vDoc.getUriByPath(docName)); + vscode.window.showTextDocument(uri, { preview: isPreview }); + + return true; + } + + // show gnu elf file + else if (suffix == '.elf') { + + const readelf = File.fromArray([ + ResManager.GetInstance().getBuilderDir(), 'readelf.exe' + ]); + + if (!readelf.IsFile()) return; + + const cont = child_process + .execFileSync(readelf.path, ['-e', binFile.path]) + .toString(); + + const vDoc = VirtualDocument.instance(); + const docName = `${binFile.path}.info`; + vDoc.updateDocument(docName, cont); + + const uri = vscode.Uri.parse(vDoc.getUriByPath(docName)); + vscode.window.showTextDocument(uri, { preview: isPreview }); + + return true; + } + + } catch (error) { + GlobalEvent.emit('msg', ExceptionToMessage(error, 'Hidden')); + } + } } From 4cffe452ce2bfa29e9062b7582336b6057cddeab Mon Sep 17 00:00:00 2001 From: null Date: Sat, 4 Dec 2021 20:46:22 +0800 Subject: [PATCH 40/48] change flasher program path type to 'input' --- src/EIDETypeDefine.ts | 183 ++++++++++++++++++++---------------------- 1 file changed, 87 insertions(+), 96 deletions(-) diff --git a/src/EIDETypeDefine.ts b/src/EIDETypeDefine.ts index 7570640d..60abb017 100644 --- a/src/EIDETypeDefine.ts +++ b/src/EIDETypeDefine.ts @@ -2278,6 +2278,46 @@ export abstract class UploadConfigModel extends ConfigModel { return 'none'; } } + + getKeyIcon(key: string): KeyIcon | undefined { + switch (key) { + case 'bin': + return 'BinaryFile_16x.svg'; + default: + return 'Property_16x.svg'; + } + } + + protected GetKeyType(key: string): FieldType { + switch (key) { + case 'bin': + return 'INPUT'; + default: + return 'Disable'; + } + } + + protected GetOpenFileFilters(key: string): OpenFileFilter | undefined { + switch (key) { + default: + return undefined; + } + } + + protected getEventData(key: string): EventData | undefined { + switch (key) { + default: + return undefined; + } + } + + protected VerifyString(key: string, input: string): string | undefined { + return undefined; + } + + protected GetSelectionList(key: string): CompileConfigPickItem[] | undefined { + return undefined; + } } class StcgalUploadModel extends UploadConfigModel { @@ -2297,13 +2337,12 @@ class StcgalUploadModel extends UploadConfigModel { getKeyIcon(key: string): KeyIcon | undefined { switch (key) { - case 'bin': case 'eepromImgPath': return 'BinaryFile_16x.svg'; case 'options': return 'ConfigurationEditor_16x.svg'; default: - return undefined; + return super.getKeyIcon(key); } } @@ -2330,40 +2369,34 @@ class StcgalUploadModel extends UploadConfigModel { } }; default: - return undefined; + return super.getEventData(key); } } protected GetKeyType(key: string): FieldType { switch (key) { - case 'bin': - return 'OPEN_FILE'; case 'eepromImgPath': return 'INPUT'; case 'options': return 'EVENT'; default: - return 'Disable'; + return super.GetKeyType(key); } } protected GetOpenFileFilters(key: string): OpenFileFilter | undefined { switch (key) { - case 'bin': - return { - 'program file': ['hex', 'bin', 's19'] - }; default: - return undefined; + return super.GetOpenFileFilters(key); } } protected VerifyString(key: string, input: string): string | undefined { - return undefined; + return super.VerifyString(key, input); } - protected GetSelectionList(key: string): CompileConfigPickItem[] { - return []; + protected GetSelectionList(key: string): CompileConfigPickItem[] | undefined { + return super.GetSelectionList(key); } GetDefault() { @@ -2409,12 +2442,10 @@ class JLinkUploadModel extends UploadConfigModel { return 'CPU_16x.svg'; case 'proType': return 'ConnectUnplugged_16x.svg'; - case 'bin': - return 'BinaryFile_16x.svg'; case 'otherCmds': return 'terminal_16x.svg'; default: - return 'Property_16x.svg'; + return super.getKeyIcon(key); } } @@ -2447,7 +2478,7 @@ class JLinkUploadModel extends UploadConfigModel { } protected getEventData(key: string): EventData | undefined { - return undefined; + return super.getEventData(key); } protected GetKeyType(key: string): FieldType { @@ -2460,21 +2491,15 @@ class JLinkUploadModel extends UploadConfigModel { return 'INPUT'; case 'speed': return 'INPUT_INTEGER'; - case 'bin': - return 'OPEN_FILE'; default: - return 'Disable'; + return super.GetKeyType(key); } } protected GetOpenFileFilters(key: string): OpenFileFilter | undefined { switch (key) { - case 'bin': - return { - 'program file': ['hex', 'bin', 's19'] - }; default: - return undefined; + return super.GetOpenFileFilters(key); } } @@ -2485,11 +2510,11 @@ class JLinkUploadModel extends UploadConfigModel { case 'baseAddr': return /^0x[0-9a-f]{1,8}$/i.test(input) ? undefined : 'must be a hex number, like: 0x08000000'; default: - return undefined; + return super.VerifyString(key, input); } } - protected GetSelectionList(key: string): CompileConfigPickItem[] { + protected GetSelectionList(key: string): CompileConfigPickItem[] | undefined { switch (key) { case 'proType': return this.protocolList.map((protocol) => { @@ -2507,7 +2532,7 @@ class JLinkUploadModel extends UploadConfigModel { }; }); default: - return []; + return super.GetSelectionList(key); } } @@ -2582,8 +2607,6 @@ class STLinkUploadModel extends UploadConfigModel { getKeyIcon(key: string): KeyIcon | undefined { switch (key) { - case 'bin': - return 'BinaryFile_16x.svg'; case 'proType': return 'ConnectUnplugged_16x.svg'; case 'optionBytes': @@ -2591,7 +2614,7 @@ class STLinkUploadModel extends UploadConfigModel { case 'otherCmds': return 'terminal_16x.svg'; default: - return 'Property_16x.svg'; + return super.getKeyIcon(key); } } @@ -2632,8 +2655,6 @@ class STLinkUploadModel extends UploadConfigModel { protected GetKeyType(key: string): FieldType { switch (key) { - case 'bin': - return 'OPEN_FILE'; case 'runAfterProgram': case 'proType': case 'resetMode': @@ -2647,18 +2668,14 @@ class STLinkUploadModel extends UploadConfigModel { case 'optionBytes': return 'EVENT'; default: - return 'Disable'; + return super.GetKeyType(key); } } protected GetOpenFileFilters(key: string): OpenFileFilter | undefined { switch (key) { - case 'bin': - return { - 'program file': ['hex', 'bin', 's19'] - }; default: - return undefined; + return super.GetOpenFileFilters(key); } } @@ -2669,11 +2686,11 @@ class STLinkUploadModel extends UploadConfigModel { case 'address': return /^0x[0-9a-f]+$/i.test(input) ? undefined : 'must be a hex number'; default: - return undefined; + return super.VerifyString(key, input); } } - protected GetSelectionList(key: string): CompileConfigPickItem[] { + protected GetSelectionList(key: string): CompileConfigPickItem[] | undefined { switch (key) { case 'runAfterProgram': return [ @@ -2719,7 +2736,7 @@ class STLinkUploadModel extends UploadConfigModel { return resultList; } default: - return []; + return super.GetSelectionList(key); } } @@ -2740,7 +2757,7 @@ class STLinkUploadModel extends UploadConfigModel { }; } default: - return undefined; + return super.getEventData(key); } } @@ -2784,32 +2801,30 @@ class StvpUploadModel extends UploadConfigModel { switch (key) { case 'deviceName': return 'SELECTION'; - case 'bin': case 'eepromFile': case 'optionByteFile': return 'INPUT'; default: - return 'Disable'; + return super.GetKeyType(key); } } getKeyIcon(key: string): KeyIcon | undefined { switch (key) { - case 'bin': case 'eepromFile': case 'optionByteFile': return 'BinaryFile_16x.svg'; case 'deviceName': return 'CPU_16x.svg'; default: - return 'Property_16x.svg'; + return super.getKeyIcon(key); } } protected GetOpenFileFilters(key: string): OpenFileFilter | undefined { switch (key) { default: - return undefined; + return super.GetOpenFileFilters(key); } } @@ -2824,11 +2839,11 @@ class StvpUploadModel extends UploadConfigModel { return 'the value must be a hex/s19 file path or \'null\''; } default: - return undefined; + return super.VerifyString(key, input); } } - protected GetSelectionList(key: string): CompileConfigPickItem[] { + protected GetSelectionList(key: string): CompileConfigPickItem[] | undefined { switch (key) { case 'deviceName': return ResManager.GetInstance().getStm8DevList() @@ -2838,12 +2853,12 @@ class StvpUploadModel extends UploadConfigModel { }; }); default: - return []; + return super.GetSelectionList(key); } } protected getEventData(key: string): EventData | undefined { - return undefined; + return super.getEventData(key); } GetDefault(): STVPFlasherOptions { @@ -2904,8 +2919,6 @@ class PyOCDUploadModel extends UploadConfigModel { getKeyIcon(key: string): KeyIcon | undefined { switch (key) { - case 'bin': - return 'BinaryFile_16x.svg'; case 'targetName': return 'CPU_16x.svg'; case 'speed': @@ -2915,14 +2928,12 @@ class PyOCDUploadModel extends UploadConfigModel { case 'config': return 'ConfigurationEditor_16x.svg'; default: - return undefined; + return super.getKeyIcon(key); } } protected GetKeyType(key: string): FieldType { switch (key) { - case 'bin': - return 'OPEN_FILE'; case 'targetName': return 'INPUT'; case 'speed': @@ -2932,18 +2943,14 @@ class PyOCDUploadModel extends UploadConfigModel { case 'config': return 'EVENT'; default: - return 'Disable'; + return super.GetKeyType(key); } } protected GetOpenFileFilters(key: string): OpenFileFilter | undefined { switch (key) { - case 'bin': - return { - 'program file': ['hex', 'bin', 's19'] - }; default: - return undefined; + return super.GetOpenFileFilters(key); } } @@ -2956,14 +2963,14 @@ class PyOCDUploadModel extends UploadConfigModel { case 'targetName': return /^[^\s]+$/i.test(input) ? undefined : 'must be a chip name, like: stm32f103c8'; default: - return undefined; + return super.VerifyString(key, input); } } - protected GetSelectionList(key: string): CompileConfigPickItem[] { + protected GetSelectionList(key: string): CompileConfigPickItem[] | undefined { switch (key) { default: - return []; + return super.GetSelectionList(key); } } @@ -2978,7 +2985,7 @@ class PyOCDUploadModel extends UploadConfigModel { } }; default: - return undefined; + return super.getEventData(key); } } @@ -3042,8 +3049,6 @@ class OpenOCDUploadModel extends UploadConfigModel { getKeyIcon(key: string): KeyIcon | undefined { switch (key) { - case 'bin': - return 'BinaryFile_16x.svg'; case 'target': return 'CPU_16x.svg'; case 'interface': @@ -3051,14 +3056,12 @@ class OpenOCDUploadModel extends UploadConfigModel { case 'baseAddr': return 'Property_16x.svg'; default: - return undefined; + return super.getKeyIcon(key); } } protected GetKeyType(key: string): FieldType { switch (key) { - case 'bin': - return 'OPEN_FILE'; case 'target': return 'SELECTION'; case 'interface': @@ -3066,18 +3069,14 @@ class OpenOCDUploadModel extends UploadConfigModel { case 'baseAddr': return 'INPUT'; default: - return 'Disable'; + return super.GetKeyType(key); } } protected GetOpenFileFilters(key: string): OpenFileFilter | undefined { switch (key) { - case 'bin': - return { - 'program file': ['hex', 's19', 'bin'] - }; default: - return undefined; + return super.GetOpenFileFilters(key); } } @@ -3086,7 +3085,7 @@ class OpenOCDUploadModel extends UploadConfigModel { case 'baseAddr': return /^0x[0-9a-f]{1,8}$/i.test(input) ? undefined : 'must be a hex number, like: 0x08000000'; default: - return undefined; + return super.VerifyString(key, input); } } @@ -3141,12 +3140,12 @@ class OpenOCDUploadModel extends UploadConfigModel { }; }); default: - return undefined; + return super.GetSelectionList(key); } } protected getEventData(key: string): EventData | undefined { - return undefined; + return super.getEventData(key); } GetDefault(): OpenOCDFlashOptions { @@ -3185,53 +3184,45 @@ class CustomUploadModel extends UploadConfigModel { getKeyIcon(key: string): KeyIcon | undefined { switch (key) { - case 'bin': - return 'BinaryFile_16x.svg'; case 'commandLine': return 'terminal_16x.svg'; default: - return undefined; + return super.getKeyIcon(key); } } protected GetKeyType(key: string): FieldType { switch (key) { - case 'bin': - return 'OPEN_FILE'; case 'commandLine': return 'INPUT'; default: - return 'Disable'; + return super.GetKeyType(key); } } protected GetOpenFileFilters(key: string): OpenFileFilter | undefined { switch (key) { - case 'bin': - return { - 'program file': ['hex', 's19', 'bin'] - }; default: - return undefined; + return super.GetOpenFileFilters(key); } } protected VerifyString(key: string, input: string): string | undefined { switch (key) { default: - return undefined; + return super.VerifyString(key, input); } } protected GetSelectionList(key: string): CompileConfigPickItem[] | undefined { switch (key) { default: - return undefined; + return super.GetSelectionList(key); } } protected getEventData(key: string): EventData | undefined { - return undefined; + return super.getEventData(key); } GetDefault(): CustomFlashOptions { From f58876e7fce3af9a29dbdbcdab9dfa263efd3358 Mon Sep 17 00:00:00 2001 From: null Date: Sun, 5 Dec 2021 00:27:38 +0800 Subject: [PATCH 41/48] allow multi program and erase flash --- res/data/template.files.options.yml | 1 + src/HexUploader.ts | 375 ++++++++++++++++++++-------- 2 files changed, 270 insertions(+), 106 deletions(-) diff --git a/res/data/template.files.options.yml b/res/data/template.files.options.yml index 30d938f8..e1a75bc6 100644 --- a/res/data/template.files.options.yml +++ b/res/data/template.files.options.yml @@ -15,6 +15,7 @@ version: '1.0' # src/*.c: -gnu -O2 ... # src/lib/**/*.cpp: --cpp11 -Os ... # !Application/*.c: -O0 +# '**/*.c': -O2 -gnu ... # # For more syntax, please refer to: https://www.npmjs.com/package/micromatch # diff --git a/src/HexUploader.ts b/src/HexUploader.ts index 23cd6473..a1d27135 100644 --- a/src/HexUploader.ts +++ b/src/HexUploader.ts @@ -47,6 +47,8 @@ let _mInstance: HexUploaderManager | undefined; export type HexUploaderType = 'JLink' | 'STVP' | 'STLink' | 'stcgal' | 'pyOCD' | 'OpenOCD' | 'Custom'; export interface UploadOption { + // program file path + // format: "[,addr1];[,addr2]" bin: string; } @@ -123,10 +125,19 @@ export class HexUploaderManager { //------------------------------------------------------ interface UploaderPreData { + isOk: boolean | Error; + params?: T; } +interface FlashProgramFile { + + path: string; + + addr?: string; +}; + export abstract class HexUploader { abstract readonly toolType: HexUploaderType; @@ -141,9 +152,9 @@ export abstract class HexUploader { this.isPowershell = /powershell.exe$/i.test(vscode.env.shell); } - async upload() { + async upload(eraseAll?: boolean) { - const dat = await this._prepare(); + const dat = await this._prepare(eraseAll); if (dat.isOk === false) { // canceled return; @@ -158,9 +169,25 @@ export abstract class HexUploader { } protected getUploadOptions(): T { - const option: T = JSON.parse(JSON.stringify(this.project.GetConfiguration().uploadConfigModel.data)); - option.bin = this.project.ToAbsolutePath(option.bin); - return option; + return JSON.parse(JSON.stringify(this.project.GetConfiguration().uploadConfigModel.data)); + } + + protected parseProgramFiles(options: T): FlashProgramFile[] { + + const result: FlashProgramFile[] = []; + const matcher = /(?[^,]+)(?:,(?0x[a-f0-9]+))?/i; + + options.bin.split(';').forEach((path) => { + const m = matcher.exec(path); + if (m && m.groups && m.groups['path']) { + result.push({ + path: this.project.ToAbsolutePath(m.groups['path']), + addr: m.groups['addr'] + }); + } + }); + + return result; } protected toAbsolute(_path: string): File { @@ -170,7 +197,7 @@ export abstract class HexUploader { return file; } - protected abstract _prepare(): Promise>; + protected abstract _prepare(eraseAll?: boolean): Promise>; protected abstract _launch(params: InvokeParamsType | undefined): void; } @@ -209,33 +236,61 @@ class JLinkUploader extends HexUploader { toolType: HexUploaderType = 'JLink'; - protected async _prepare(): Promise> { + protected async _prepare(eraseAll?: boolean): Promise> { if (!new File(SettingManager.GetInstance().getJlinkDir()).IsDir()) { await ResInstaller.instance().setOrInstallTools(this.toolType, `Not found 'JLink' install directory !`); return { isOk: false }; } - const option = this.getUploadOptions(); + const jlinkCmdFileLines: string[] = []; // create output dir const outFolder = new File(this.project.ToAbsolutePath(this.project.getOutputDir())); outFolder.CreateDir(true); + const jlinkCommandsFile = File.fromArray([outFolder.path, 'commands.jlink']); - // clear base addr for hex file - if (/\.hex$/i.test(option.bin)) { - option.baseAddr = undefined; + const option = this.getUploadOptions(); + const files = this.parseProgramFiles(option); + + // program + if (!eraseAll) { + + if (files.length == 0) { + return { isOk: new Error(`no any program files !`) }; + } + + jlinkCmdFileLines.push( + 'r', + 'halt' + ); + + files.forEach((file) => { + if (/\.bin$/i.test(file.path)) { + const addr = file.addr || option.baseAddr + jlinkCmdFileLines.push(`loadfile "${file.path}"${addr ? (`,${addr}`) : ''}`); + } else { + jlinkCmdFileLines.push(`loadfile "${file.path}"`); + } + }); + + jlinkCmdFileLines.push( + 'r', + 'go', + 'exit' + ); } - const jlinkCommandsFile = File.fromArray([outFolder.path, 'commands.jlink']); - const jlinkCmdFileLines: string[] = [ - 'r', - 'halt', - `loadfile "${option.bin}"${option.baseAddr ? (`,${option.baseAddr}`) : ''}`, - 'r', - 'go', - 'exit' - ]; + // erase internal falsh + else { + jlinkCmdFileLines.push( + 'r', + 'halt', + 'erase', + 'r', + 'exit' + ); + } const codeConverter = new CodeConverter(); const codePage = ResManager.getLocalCodePage(); @@ -301,7 +356,7 @@ class StcgalUploader extends HexUploader { super(prj); } - protected async _prepare(): Promise> { + protected async _prepare(eraseAll?: boolean): Promise> { const resManager = ResManager.GetInstance(); @@ -385,8 +440,13 @@ class StcgalUploader extends HexUploader { protected _launch(commands: string[]): void { const option = this.getUploadOptions(); + const programs = this.parseProgramFiles(option); + + if (programs.length == 0) { + throw new Error(`no any program files !`); + } - commands.push('"' + option.bin + '"'); + commands.push('"' + programs[0].path + '"'); const eepromFile = this.toAbsolute(option.eepromImgPath); if (eepromFile.IsFile()) { @@ -430,10 +490,15 @@ class STLinkUploader extends HexUploader { super(prj); } - private genCommandForStlinkCli(exe: File): string[] { + private genCommandForStlinkCli(exe: File, eraseAll?: boolean): string[] { const commands: string[] = []; const options = this.getUploadOptions(); + const programs = this.parseProgramFiles(options); + + if (programs.length == 0) { + throw new Error(`no any program files !`); + } /* connection commands */ commands.push( @@ -447,35 +512,45 @@ class STLinkUploader extends HexUploader { } /* flash commands */ - commands.push( - '-P', options.bin - ); + if (!eraseAll) { - if (/\.bin$/i.test(options.bin)) { - commands.push(options.address || '0x08000000'); - } + commands.push( + '-P', programs[0].path + ); - if (/\.stldr$/i.test(options.elFile)) { - const elFolder = File.fromArray([NodePath.dirname(exe.path), 'ExternalLoader']); - commands.push('-EL', options.elFile.replace('', elFolder.path)); - } + if (/\.bin$/i.test(programs[0].path)) { + commands.push(options.address || programs[0].addr || '0x08000000'); + } - // option bytes commands - const optionFile = new File(this.project.ToAbsolutePath(options.optionBytes)); - if (optionFile.IsFile()) { - const conf = ini.parse(optionFile.Read()); - const confList: string[] = []; - for (const key in conf) { confList.push(`${key}=${conf[key]}`) } - if (confList.length > 0) { - commands.push('-OB'); - confList.forEach((val) => { commands.push(val) }); - commands.push('-rOB'); + if (/\.stldr$/i.test(options.elFile)) { + const elFolder = File.fromArray([NodePath.dirname(exe.path), 'ExternalLoader']); + commands.push('-EL', options.elFile.replace('', elFolder.path)); + } + + // option bytes commands + const optionFile = new File(this.project.ToAbsolutePath(options.optionBytes)); + if (optionFile.IsFile()) { + const conf = ini.parse(optionFile.Read()); + const confList: string[] = []; + for (const key in conf) { confList.push(`${key}=${conf[key]}`) } + if (confList.length > 0) { + commands.push('-OB'); + confList.forEach((val) => { commands.push(val) }); + commands.push('-rOB'); + } } + + commands.push( + '-V', 'after_programming' + ); } - commands.push( - '-V', 'after_programming' - ); + // eraseAll + else { + commands.push( + '-ME' + ); + } /* misc commands */ commands.push( @@ -490,10 +565,15 @@ class STLinkUploader extends HexUploader { return commands; } - private genCommandForCubeProgramer(exe: File): string[] { + private genCommandForCubeProgramer(exe: File, eraseAll?: boolean): string[] { const commands: string[] = []; const options = this.getUploadOptions(); + const programs = this.parseProgramFiles(options); + + if (programs.length == 0) { + throw new Error(`no any program files !`); + } /* connect cmd */ commands.push('-c', `port=${options.proType}`, `freq=${options.speed}`); @@ -503,41 +583,52 @@ class STLinkUploader extends HexUploader { commands.push(`reset=${options.resetMode}`); } - /* external loader */ - if (/\.stldr$/i.test(options.elFile)) { - const elFolder = File.fromArray([NodePath.dirname(exe.path), 'ExternalLoader']); - commands.push('-el', options.elFile.replace('', elFolder.path)); - } + // program + if (!eraseAll) { - // option bytes commands - const optionFile = new File(this.project.ToAbsolutePath(options.optionBytes)); - if (optionFile.IsFile()) { - const conf = ini.parse(optionFile.Read()); - const confList: string[] = []; - for (const key in conf) { confList.push(`${key}=${conf[key]}`) } - if (confList.length > 0) { - commands.push('-ob'); - confList.forEach((val) => { commands.push(val) }); - commands.push('-ob', 'displ'); + /* external loader */ + if (/\.stldr$/i.test(options.elFile)) { + const elFolder = File.fromArray([NodePath.dirname(exe.path), 'ExternalLoader']); + commands.push('-el', options.elFile.replace('', elFolder.path)); } - } - /* download program */ - commands.push('--download', options.bin); + // option bytes commands + const optionFile = new File(this.project.ToAbsolutePath(options.optionBytes)); + if (optionFile.IsFile()) { + const conf = ini.parse(optionFile.Read()); + const confList: string[] = []; + for (const key in conf) { confList.push(`${key}=${conf[key]}`) } + if (confList.length > 0) { + commands.push('-ob'); + confList.forEach((val) => { commands.push(val) }); + commands.push('-ob', 'displ'); + } + } + + /* download program */ + commands.push('--download', programs[0].path); + + if (/\.bin$/i.test(programs[0].path)) { + commands.push(options.address || programs[0].addr || '0x08000000'); + } - if (/\.bin$/i.test(options.bin)) { - commands.push(options.address || '0x08000000'); + /* verify program */ + commands.push('-v'); } - /* verify program */ - commands.push('-v'); + // erase all + else { + commands.push( + '-e', 'all' + ); + } if (options.runAfterProgram) { commands.push('--go') } return commands; } - protected async _prepare(): Promise> { + protected async _prepare(eraseAll?: boolean): Promise> { const exe = new File(SettingManager.GetInstance().getSTLinkExePath()); if (!exe.IsFile()) { @@ -549,12 +640,12 @@ class STLinkUploader extends HexUploader { /* use stlink cli */ if (exe.noSuffixName.toLowerCase().startsWith('st-link_cli')) { - commands = this.genCommandForStlinkCli(exe); + commands = this.genCommandForStlinkCli(exe, eraseAll); } /* use cube programer */ else { - commands = this.genCommandForCubeProgramer(exe); + commands = this.genCommandForCubeProgramer(exe, eraseAll); } return { @@ -596,7 +687,7 @@ class STVPHexUploader extends HexUploader { super(prj); } - protected async _prepare(): Promise> { + protected async _prepare(eraseAll?: boolean): Promise> { const exe = new File(SettingManager.GetInstance().getStvpExePath()); if (!exe.IsFile()) { @@ -605,6 +696,8 @@ class STVPHexUploader extends HexUploader { } const options = this.getUploadOptions(); + const programs = this.parseProgramFiles(options); + const commands: string[] = []; // connection commands @@ -618,28 +711,41 @@ class STVPHexUploader extends HexUploader { commands.push('-no_loop'); commands.push('-no_log'); - // not verify - commands.push('-no_verif'); + // program + if (!eraseAll) { - const binFile = this.toAbsolute(options.bin); - if (binFile.IsFile()) { - commands.push('-FileProg=\"' + binFile.path + '\"'); - } else { - commands.push('-no_progProg'); - } + if (programs.length == 0) { + throw new Error(`no any program files !`); + } - const eepromFile = this.toAbsolute(options.eepromFile); - if (eepromFile.IsFile()) { - commands.push('-FileData=\"' + eepromFile.path + '\"'); - } else { - commands.push('-no_progData'); + // not verify + commands.push('-no_verif'); + + const binFile = this.toAbsolute(programs[0].path); + if (binFile.IsFile()) { + commands.push('-FileProg=\"' + binFile.path + '\"'); + } else { + commands.push('-no_progProg'); + } + + const eepromFile = this.toAbsolute(options.eepromFile); + if (eepromFile.IsFile()) { + commands.push('-FileData=\"' + eepromFile.path + '\"'); + } else { + commands.push('-no_progData'); + } + + const opFile = this.toAbsolute(options.optionByteFile); + if (opFile.IsFile()) { + commands.push('-FileOption=\"' + opFile.path + '\"'); + } else { + commands.push('-no_progOption'); + } } - const opFile = this.toAbsolute(options.optionByteFile); - if (opFile.IsFile()) { - commands.push('-FileOption=\"' + opFile.path + '\"'); - } else { - commands.push('-no_progOption'); + // erase all + else { + commands.push('-erase'); } return { @@ -677,10 +783,27 @@ class PyOCDUploader extends HexUploader { toolType: HexUploaderType = 'pyOCD'; - protected async _prepare(): Promise> { + protected async _prepare(eraseAll?: boolean): Promise> { const commandLines: string[] = []; + const option = this.getUploadOptions(); + const programs = this.parseProgramFiles(option); + + // program + if (!eraseAll) { + + if (programs.length == 0) { + throw new Error(`no any program files !`); + } + + commandLines.push('flash'); + } + + // erase all + else { + commandLines.push('erase'); + } if (option.config) { const confFile = new File(this.project.ToAbsolutePath(option.config)); @@ -690,11 +813,6 @@ class PyOCDUploader extends HexUploader { } } - if (/\.bin$/i.test(option.bin)) { - commandLines.push('-a'); - commandLines.push(option.baseAddr || '0x08000000'); - } - // target name commandLines.push('-t'); commandLines.push(option.targetName); @@ -706,7 +824,16 @@ class PyOCDUploader extends HexUploader { } // file path - commandLines.push(option.bin); + if (!eraseAll) { + programs.forEach((file) => { + if (/\.bin$/i.test(file.path)) { + const baseAddr = option.baseAddr || programs[0].addr || '0x08000000'; + commandLines.push(`${file.path}@${baseAddr}`); + } else { + commandLines.push(file.path); + } + }); + } return { isOk: true, @@ -716,7 +843,7 @@ class PyOCDUploader extends HexUploader { protected _launch(commands: string[]): void { - const commandLine: string = 'python -m pyocd flash ' + commands.map((line) => { + const commandLine: string = 'python -m pyocd ' + commands.map((line) => { return CmdLineHandler.quoteString(line, '"'); }).join(' '); @@ -741,7 +868,7 @@ class OpenOCDUploader extends HexUploader { toolType: HexUploaderType = 'OpenOCD'; - protected async _prepare(): Promise> { + protected async _prepare(eraseAll?: boolean): Promise> { const exe = new File(SettingManager.GetInstance().getOpenOCDExePath()); if (!exe.IsFile()) { @@ -750,7 +877,12 @@ class OpenOCDUploader extends HexUploader { } const option = this.getUploadOptions(); - const addrStr = /\.bin$/i.test(option.bin) ? (option.baseAddr || '0x08000000') : ''; + const programs = this.parseProgramFiles(option); + + if (programs.length == 0) { + throw new Error(`no any program files !`); + } + const commands: string[] = []; const interfaceFileName = option.interface.startsWith('${workspaceFolder}/') @@ -770,10 +902,20 @@ class OpenOCDUploader extends HexUploader { `-f ${interfaceFileName}.cfg`, `-f ${targetFileName}.cfg`, `-c "init"`, - `-c "reset init"`, - `-c "program \\"${option.bin.replace(/\\{1,}/g, '/')}\\" ${addrStr} verify reset exit"` + `-c "reset init"` ); + programs.forEach(file => { + if (/\.bin$/i.test(file.path)) { + const addrStr = option.baseAddr || file.addr || '0x08000000'; + commands.push(`-c "program \\"${file.path.replace(/\\{1,}/g, '/')}\\" ${addrStr} verify reset"`); + } else { + commands.push(`-c "program \\"${file.path.replace(/\\{1,}/g, '/')}\\" verify reset"`); + } + }); + + commands.push(`-c "exit"`); + return { isOk: true, params: commands @@ -797,9 +939,16 @@ class CustomUploader extends HexUploader { toolType: HexUploaderType = 'Custom'; - protected async _prepare(): Promise> { + protected async _prepare(eraseAll?: boolean): Promise> { const option = this.getUploadOptions(); + const programs = this.parseProgramFiles(option); + + if (programs.length == 0) { + return { + isOk: new Error(`no any program files !`) + }; + } if (option.commandLine === undefined) { return { @@ -808,10 +957,24 @@ class CustomUploader extends HexUploader { } const portList = ResManager.GetInstance().enumSerialPort(); - const commandLine = option.commandLine - .replace(/\$\{hexFile\}|\$\{binFile\}|\$\{programFile\}/ig, option.bin) + + let commandLine = option.commandLine + .replace(/\$\{hexFile\}|\$\{binFile\}|\$\{programFile\}/ig, programs[0].path) .replace(/\$\{port\}/ig, portList[0] || 'none'); + programs.forEach((file, index) => { + + commandLine = commandLine + .replace(`\${hexFile[${index}]}`, file.path) + .replace(`\${binFile[${index}]}`, file.path) + .replace(`\${programFile[${index}]}`, file.path); + + if (file.addr) { + commandLine = commandLine + .replace(`\${binAddr[${index}]}`, file.addr || '0x00000000') + } + }); + return { isOk: true, params: commandLine From d618f19c6bf45880aa3eebfe413ca2fa55fd15f6 Mon Sep 17 00:00:00 2001 From: null Date: Sun, 5 Dec 2021 00:57:10 +0800 Subject: [PATCH 42/48] add erase all command --- package.json | 9 +++++++++ package.nls.json | 1 + package.nls.zh-CN.json | 1 + src/EIDEProject.ts | 5 +++-- src/EIDEProjectExplorer.ts | 4 ++-- src/HexUploader.ts | 2 +- src/extension.ts | 1 + 7 files changed, 18 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 59fc535d..e0121156 100644 --- a/package.json +++ b/package.json @@ -657,6 +657,15 @@ "light": "./res/icon/TransferDownload_16x.svg" } }, + { + "command": "eide.project.flash.erase.all", + "title": "%eide.project.flash.erase.all%", + "category": "eide", + "icon": { + "dark": "./res/icon/TransferDownload_16x.svg", + "light": "./res/icon/TransferDownload_16x.svg" + } + }, { "command": "_cl.eide.project.showBuildParams", "title": "%eide.project.show.commands%" diff --git a/package.nls.json b/package.nls.json index 64661f22..12d882bb 100644 --- a/package.nls.json +++ b/package.nls.json @@ -24,6 +24,7 @@ "eide.project.rebuild": "Rebuild", "eide.project.clean": "Clean", "eide.project.upload": "Upload Program To Device", + "eide.project.flash.erase.all": "Erase Chip", "eide.project.gen.makefile": "Generate Makefile Template", "eide.project.modify.files.options": "Append separate compiler options to the file", "eide.project.import.ext.project.src.struct": "Import source file resources from other IDE's project", diff --git a/package.nls.zh-CN.json b/package.nls.zh-CN.json index 759864bf..67929331 100644 --- a/package.nls.zh-CN.json +++ b/package.nls.zh-CN.json @@ -24,6 +24,7 @@ "eide.project.rebuild": "重新构建", "eide.project.clean": "清理", "eide.project.upload": "烧录", + "eide.project.flash.erase.all": "擦除芯片", "eide.project.gen.makefile": "生成 Makefile 模板", "eide.project.modify.files.options": "为文件附加单独的编译选项", "eide.project.import.ext.project.src.struct": "从其他 IDE 的项目中导入源文件资源", diff --git a/src/EIDEProject.ts b/src/EIDEProject.ts index b0b557b6..beada909 100644 --- a/src/EIDEProject.ts +++ b/src/EIDEProject.ts @@ -1169,9 +1169,10 @@ export abstract class AbstractProject { this.reloadUploader(oldUploader); } + // @deprecated updateUploaderHexFile(notEmitEvent?: boolean) { // set upload file path if prev value is not existed - const prevBinFile = new File(this.ToAbsolutePath(this.GetConfiguration().uploadConfigModel.getKeyValue('bin'))); + /* const prevBinFile = new File(this.ToAbsolutePath(this.GetConfiguration().uploadConfigModel.getKeyValue('bin'))); if (!prevBinFile.IsFile()) { const binPath = this.getOutputDir() + File.sep + this.GetConfiguration().config.name + '.hex'; if (notEmitEvent) { @@ -1179,7 +1180,7 @@ export abstract class AbstractProject { } else { this.GetConfiguration().uploadConfigModel.SetKeyValue('bin', binPath); } - } + } */ } //-- diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index 61647807..ebd047e5 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -2171,7 +2171,7 @@ export class ProjectExplorer { } private _uploadLock: boolean = false; - async UploadToDevice(prjItem?: ProjTreeItem) { + async UploadToDevice(prjItem?: ProjTreeItem, eraseAll?: boolean) { const prj = this.getProjectByTreeItem(prjItem); @@ -2189,7 +2189,7 @@ export class ProjectExplorer { const uploader = HexUploaderManager.getInstance().createUploader(prj); try { - await uploader.upload(); + await uploader.upload(eraseAll); } catch (error) { GlobalEvent.emit('error', error); } diff --git a/src/HexUploader.ts b/src/HexUploader.ts index a1d27135..26d47b05 100644 --- a/src/HexUploader.ts +++ b/src/HexUploader.ts @@ -802,7 +802,7 @@ class PyOCDUploader extends HexUploader { // erase all else { - commandLines.push('erase'); + commandLines.push('erase', '--chip'); } if (option.config) { diff --git a/src/extension.ts b/src/extension.ts index 46d5ba0f..083c1687 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -107,6 +107,7 @@ export async function activate(context: vscode.ExtensionContext) { subscriptions.push(vscode.commands.registerCommand('eide.project.clean', (item) => projectExplorer.BuildClean(item))); subscriptions.push(vscode.commands.registerCommand('eide.project.uploadToDevice', (item) => projectExplorer.UploadToDevice(item))); subscriptions.push(vscode.commands.registerCommand('eide.reinstall.binaries', () => checkAndInstallBinaries(context, true))); + subscriptions.push(vscode.commands.registerCommand('eide.project.flash.erase.all', (item) => projectExplorer.UploadToDevice(item, true))); // operations bar subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.historyRecord', () => projectExplorer.openHistoryRecords())); From abf5c17c91980edc4be3c6eefce1c40f6f07f825 Mon Sep 17 00:00:00 2001 From: null Date: Sun, 5 Dec 2021 01:43:41 +0800 Subject: [PATCH 43/48] support default hex path for empty value --- src/EIDETypeDefine.ts | 36 ++++++++++++++++++++++-------------- src/HexUploader.ts | 11 +++++++++++ 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/EIDETypeDefine.ts b/src/EIDETypeDefine.ts index 60abb017..127b311c 100644 --- a/src/EIDETypeDefine.ts +++ b/src/EIDETypeDefine.ts @@ -2287,6 +2287,15 @@ export abstract class UploadConfigModel extends ConfigModel { return 'Property_16x.svg'; } } + + getKeyValue(key: string): string { + switch (key) { + case 'bin': + return (this.data)[key] || '${projectName}.hex'; + default: + return (this.data)[key] || 'null'; + } + } protected GetKeyType(key: string): FieldType { switch (key) { @@ -2351,7 +2360,7 @@ class StcgalUploadModel extends UploadConfigModel { case 'options': return 'Object {...}'; default: - return (this.data)[key] || 'null'; + return super.getKeyValue(key); } } @@ -2401,7 +2410,7 @@ class StcgalUploadModel extends UploadConfigModel { GetDefault() { return { - bin: 'null', + bin: '', eepromImgPath: 'null', options: `${AbstractProject.EIDE_DIR}/stc.flash.json` }; @@ -2473,7 +2482,7 @@ class JLinkUploadModel extends UploadConfigModel { case 'cpuInfo': return this.data.cpuInfo.cpuName; default: - return (this.data)[key] || 'null'; + return super.getKeyValue(key); } } @@ -2538,7 +2547,7 @@ class JLinkUploadModel extends UploadConfigModel { GetDefault(): JLinkOptions { return { - bin: 'null', + bin: '', baseAddr: '0x08000000', cpuInfo: { vendor: 'ST', @@ -2649,7 +2658,7 @@ class STLinkUploadModel extends UploadConfigModel { case 'elFile': return NodePath.basename(this.data.elFile); default: - return (this.data)[key] || 'null'; + return super.getKeyValue(key); } } @@ -2794,7 +2803,7 @@ class StvpUploadModel extends UploadConfigModel { } getKeyValue(key: string): string { - return (this.data)[key]; + return super.getKeyValue(key); } protected GetKeyType(key: string): FieldType { @@ -2830,7 +2839,6 @@ class StvpUploadModel extends UploadConfigModel { protected VerifyString(key: string, input: string): string | undefined { switch (key) { - case 'bin': case 'eepromFile': case 'optionByteFile': if (/(?:\.hex|\.s19)$/i.test(input) || /^null$/.test(input)) { @@ -2864,7 +2872,7 @@ class StvpUploadModel extends UploadConfigModel { GetDefault(): STVPFlasherOptions { return { deviceName: 'STM8S105x4', - bin: 'null', + bin: '', eepromFile: 'null', optionByteFile: 'null' }; @@ -2904,7 +2912,7 @@ class PyOCDUploadModel extends UploadConfigModel { case 'config': return 'Object {...}'; default: - return (this.data)[key] || 'null'; + return super.getKeyValue(key); } } @@ -2991,7 +2999,7 @@ class PyOCDUploadModel extends UploadConfigModel { GetDefault(): PyOCDFlashOptions { return { - bin: 'null', + bin: '', targetName: 'cortex_m', baseAddr: '0x08000000', speed: '4M', @@ -3034,7 +3042,7 @@ class OpenOCDUploadModel extends UploadConfigModel { } return 'null'; default: - return (this.data)[key] || 'null'; + return super.getKeyValue(key); } } @@ -3150,7 +3158,7 @@ class OpenOCDUploadModel extends UploadConfigModel { GetDefault(): OpenOCDFlashOptions { return { - bin: 'null', + bin: '', target: 'stm32f1x', interface: 'stlink', baseAddr: '0x08000000' @@ -3172,7 +3180,7 @@ class CustomUploadModel extends UploadConfigModel { } getKeyValue(key: string): string { - return (this.data)[key] || 'null'; + return super.getKeyValue(key); } isKeyEnable(key: string): boolean { @@ -3227,7 +3235,7 @@ class CustomUploadModel extends UploadConfigModel { GetDefault(): CustomFlashOptions { return { - bin: 'null', + bin: '', commandLine: 'null' }; } diff --git a/src/HexUploader.ts b/src/HexUploader.ts index 26d47b05..020f1c21 100644 --- a/src/HexUploader.ts +++ b/src/HexUploader.ts @@ -177,6 +177,17 @@ export abstract class HexUploader { const result: FlashProgramFile[] = []; const matcher = /(?[^,]+)(?:,(?0x[a-f0-9]+))?/i; + // if 'bin' path is empty, use default program path + if (options.bin.trim() === '') { + + const hexPath = [ + this.project.getOutputDir(), + this.project.GetConfiguration().config.name + '.hex' + ].join(File.sep); + + return [{ path: this.project.ToAbsolutePath(hexPath) }]; + } + options.bin.split(';').forEach((path) => { const m = matcher.exec(path); if (m && m.groups && m.groups['path']) { From f9ab24d2582c5bc0878cb84ebb5e68cc0e1953ec Mon Sep 17 00:00:00 2001 From: null Date: Sun, 5 Dec 2021 15:56:50 +0800 Subject: [PATCH 44/48] optimize importer --- src/EIDEProject.ts | 1 + src/EIDEProjectExplorer.ts | 50 +++++++++++++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/EIDEProject.ts b/src/EIDEProject.ts index beada909..364d46cb 100644 --- a/src/EIDEProject.ts +++ b/src/EIDEProject.ts @@ -2023,6 +2023,7 @@ class EIDEProject extends AbstractProject { let recommendExt: string[] = [ "cl.eide", "keroc.hex-fmt", + "xiaoyongdong.srecord", "hars.cppsnippets", "zixuanwang.linkerscript", "redhat.vscode-yaml" diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index ebd047e5..8153c6bd 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -1812,6 +1812,8 @@ interface BuildCommandInfo { } interface ImporterProjectInfo { + name: string; + target?: string; incList: string[]; defineList: string[]; files: VirtualFolder; @@ -3372,9 +3374,8 @@ export class ProjectExplorer { location: vscode.ProgressLocation.Notification, title: `Importing Resources` }, (progress) => { - return new Promise((resolve) => { + return new Promise(async (resolve) => { try { - progress.report({ message: `running importer ...` }); // @@ -3385,13 +3386,54 @@ export class ProjectExplorer { const cmds = ['--std', './importer/index.js', imptrName, prjFile.path]; const result = child_process.execFileSync(`${scriptRoot.path}/qjs.exe`, cmds, { cwd: scriptRoot.path }).toString(); - let prjInfo: ImporterProjectInfo; + let prjList: ImporterProjectInfo[]; try { - prjInfo = JSON.parse(result); + prjList = JSON.parse(result); + if (!Array.isArray(prjList)) throw new Error('project list must be an array !'); } catch (error) { throw new Error(`Import Error !, msg: '${result}'`); } + // + // select project + // + let prjInfo: ImporterProjectInfo | undefined; + + if (prjList.length > 0) { + // if have multi project, select one to import + if (prjList.length > 1) { + const item = await vscode.window.showQuickPick( + prjList.map((prj) => { + return { + label: prj.name, + description: prj.target, + detail: `${prjFile.name} -> ${prj.name}${prj.target ? (': ' + prj.target) : ''}` + } + }), + { + placeHolder: `Found ${prjList.length} sub project, select one to import`, + ignoreFocusOut: true, + canPickMany: false + } + ); + if (item != undefined) { + const index = prjList.findIndex((prj) => prj.name == item.label); + if (index != -1) { + prjInfo = prjList[index]; + } + } + } + // if only have one, use it + else { + prjInfo = prjList[0]; + } + } + + if (prjInfo == undefined) { + resolve(); + return; + } + // // start import project // From 2fc9d2bfda64b304dfd0146fce488312c18e5f83 Mon Sep 17 00:00:00 2001 From: null Date: Sun, 5 Dec 2021 16:11:37 +0800 Subject: [PATCH 45/48] support armcc disasm --- src/EIDEProjectExplorer.ts | 56 ++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index 8153c6bd..5298f685 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -2871,39 +2871,61 @@ export class ProjectExplorer { async showDisassembly(uri: vscode.Uri) { + const supportList = ['RISCV_GCC', 'GCC', 'AC5', 'AC6']; + try { - /* parser ref json */ + // check condition const activePrj = this.dataProvider.getActiveProject(); if (!activePrj) { throw new Error('Not found active project !'); } const toolchainName = activePrj.getToolchain().name; - if (!['RISCV_GCC', 'GCC'].includes(toolchainName)) { throw new Error('Only support GCC compiler !'); } + if (!supportList.includes(toolchainName)) { + throw new Error(`Only support '${supportList.join(',')}' compiler !`); + } + + // parser ref json const srcPath = uri.fsPath; const refFile = File.fromArray([activePrj.ToAbsolutePath(activePrj.getOutputDir()), 'ref.json']); if (!refFile.IsFile()) { throw new Error(`Not found 'ref.json' at output folder, you need build project !`) } const ref = JSON.parse(refFile.Read()); if (!ref[srcPath]) { throw new Error(`Not found any reference for this source file !`) } - /* get obj file */ + // get obj file let objPath: string | undefined; - - if (typeof ref[srcPath] == 'string') { - objPath = ref[srcPath]; - } else if (Array.isArray(ref[srcPath])) { - objPath = ref[srcPath][0]; - } - + if (typeof ref[srcPath] == 'string') { objPath = ref[srcPath]; } + else if (Array.isArray(ref[srcPath])) { objPath = ref[srcPath][0]; } if (objPath == undefined) { throw new Error(`Not found any reference for this source file !`) } - /* get objdump.exe */ - const toolPrefix = toolchainName == 'GCC' ? - SettingManager.GetInstance().getGCCPrefix() : - SettingManager.GetInstance().getRiscvToolPrefix(); - const exeFile = File.fromArray([activePrj.getToolchain().getToolchainDir().path, 'bin', `${toolPrefix}objdump.exe`]); - if (!exeFile.IsFile()) { throw Error(`Not found '${exeFile.name}' !`) } + // prepare command + let exeFile: File; + let cmds: string[]; + + switch (toolchainName) { + case 'GCC': + case 'RISCV_GCC': + { + const toolPrefix = toolchainName == 'GCC' ? + SettingManager.GetInstance().getGCCPrefix() : + SettingManager.GetInstance().getRiscvToolPrefix(); + exeFile = File.fromArray([activePrj.getToolchain().getToolchainDir().path, 'bin', `${toolPrefix}objdump.exe`]); + if (!exeFile.IsFile()) { throw Error(`Not found '${exeFile.name}' !`) } + cmds = ['-S', objPath]; + } + break; + case 'AC5': + case 'AC6': + { + exeFile = File.fromArray([activePrj.getToolchain().getToolchainDir().path, 'bin', `fromelf.exe`]); + if (!exeFile.IsFile()) { throw Error(`Not found '${exeFile.name}' !`) } + cmds = ['-c', objPath]; + } + break; + default: + throw new Error(`Only support '${supportList.join(',')}' compiler !`); + } /* executable */ - const asmTxt = child_process.execFileSync(exeFile.path, ['-S', objPath], { encoding: 'ascii' }); + const asmTxt = child_process.execFileSync(exeFile.path, cmds, { encoding: 'ascii' }); const asmFile = `${srcPath}.edasm`; const asmFileUri = vscode.Uri.parse(VirtualDocument.instance().getUriByPath(asmFile)); VirtualDocument.instance().updateDocument(asmFile, asmTxt); From 60158c50fc5943d9fd003e06c797f6d26555dfad Mon Sep 17 00:00:00 2001 From: null Date: Sun, 5 Dec 2021 23:42:03 +0800 Subject: [PATCH 46/48] optimize --- src/EIDEProjectExplorer.ts | 49 ++++++++++++++++++++++++++++---------- src/StringTable.ts | 14 +++++------ src/extension.ts | 24 ++++++++++--------- 3 files changed, 56 insertions(+), 31 deletions(-) diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index 5298f685..fd4cdc3a 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -417,9 +417,11 @@ export class ProjTreeItem extends vscode.TreeItem { name = 'TransferDownload_16x.svg'; break; case TreeItemType.DEPENDENCE_GROUP: - case TreeItemType.DEPENDENCE: name = 'DependencyGraph_16x.svg'; break; + case TreeItemType.DEPENDENCE: + name = 'Property_16x.svg'; + break; case TreeItemType.SETTINGS: name = 'Settings_16x.svg'; break; @@ -1082,15 +1084,17 @@ class ProjectDataProvider implements vscode.TreeDataProvider { case TreeItemType.OUTPUT_FOLDER: { const outFolder = project.getOutputFolder(); - const fList = outFolder.GetList([AbstractProject.buildOutputMatcher], File.EMPTY_FILTER); - fList.forEach((file) => { - iList.push(new ProjTreeItem(TreeItemType.OUTPUT_FILE_ITEM, { - value: file, - collapsibleState: vscode.TreeItemCollapsibleState.None, - projectIndex: element.val.projectIndex, - tooltip: file.path, - })); - }); + if (outFolder.IsDir()) { + const fList = outFolder.GetList([AbstractProject.buildOutputMatcher], File.EMPTY_FILTER); + fList.forEach((file) => { + iList.push(new ProjTreeItem(TreeItemType.OUTPUT_FILE_ITEM, { + value: file, + collapsibleState: vscode.TreeItemCollapsibleState.None, + projectIndex: element.val.projectIndex, + tooltip: file.path, + })); + }); + } } break; // output file item @@ -1904,9 +1908,10 @@ export class ProjectExplorer { let targetName = await vscode.window.showInputBox({ placeHolder: 'Input a target name', + ignoreFocusOut: true, validateInput: (val: string) => { if (val.length > 25) { return `string is too long !, length must < 25, current is ${val.length}`; } - if (!/^[\w-]+$/.test(val)) { return `string can only contain word, number or '_' !`; } + if (!/^[\w\-]+$/.test(val)) { return `string can only contain word, number '-' or '_' !`; } return undefined; } }); @@ -2811,8 +2816,9 @@ export class ProjectExplorer { const curFolder = item.val.obj; const folderName = await vscode.window.showInputBox({ - placeHolder: 'Input the new name', + prompt: 'Input the new name', ignoreFocusOut: true, + value: curFolder.vFolder.name, validateInput: (input) => { if (!this.vFolderNameMatcher.test(input)) { return `must match '${this.vFolderNameMatcher.source}'`; } return undefined; @@ -3456,12 +3462,29 @@ export class ProjectExplorer { return; } + // make abs path to relative path + const formatVirtualFolder = (vFolderRoot: VirtualFolder) => { + const folderStack: VirtualFolder[] = [vFolderRoot]; + while (folderStack.length > 0) { + const vFolder = folderStack.pop(); + if (vFolder) { + vFolder.files = vFolder.files.map((file) => { + return { path: prj.ToRelativePath(file.path) || file.path } + }); + vFolder.folders.forEach((folder) => { + folderStack.push(folder) + }); + } + } + }; + // // start import project // const prj = this.dataProvider.GetProjectByIndex(item.val.projectIndex); const prjConf = prj.GetConfiguration(); prjConf.config.virtualFolder = prjInfo.files; + formatVirtualFolder(prjConf.config.virtualFolder); const deps = prjConf.CustomDep_getDependence(); deps.incList = prjInfo.incList; deps.libList = []; @@ -3997,7 +4020,7 @@ export class ProjectExplorer { // push macros yamlLines.push( ``, - `# Global Macro Defines`, + `# Preprocessor Definitions`, `Defines:`, `# - TEST=1` ); diff --git a/src/StringTable.ts b/src/StringTable.ts index 2555952d..695a92b1 100644 --- a/src/StringTable.ts +++ b/src/StringTable.ts @@ -240,8 +240,8 @@ export const view_str$project$sel_target = [ ][langIndex]; export const view_str$project$other_settings = [ - '其他设置', - 'Other Settings' + '项目设置', + 'Project Settings' ][langIndex]; export const view_str$project$cmsis_components = [ @@ -280,7 +280,7 @@ export const include_desc = [ ][langIndex]; export const lib_desc = [ - '库目录', + '链接库目录', 'Library Directories' ][langIndex]; @@ -290,13 +290,13 @@ export const source_dir_desc = [ ][langIndex]; export const definition_list_desc = [ - '宏定义', - 'Macro List' + '预处理器定义', + 'Preprocessor Definitions' ][langIndex]; export const project_dependence = [ - '项目依赖', - 'Project Dependences' + '项目属性', + 'Project Attributes' ][langIndex]; export const view_str$dialog$add_to_source_folder = [ diff --git a/src/extension.ts b/src/extension.ts index 083c1687..b4bd7103 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -583,21 +583,14 @@ class MapViewEditorProvider implements vscode.CustomTextEditorProvider { webviewPanel.onDidDispose(() => this.deleteRef(viewFile.path, uid)); if (!viewFile.IsFile()) { - webviewPanel.webview.html = this.genHtmlCont(title, `Error: file '${viewFile.path}' is not a file !`); + webviewPanel.webview.html = this.genHtmlCont(title, `Error: Not found file '${viewFile.path}' !`); return; } + // check tool type const conf: { tool?: string, fileName?: string } = yaml.parse(viewFile.Read()); - const defName = viewFile.noSuffixName + '.map'; - const mapFile = File.fromArray([viewFile.dir, conf.fileName || defName]); - - if (!mapFile.IsFile()) { - webviewPanel.webview.html = this.genHtmlCont(title, `Error: file '${mapFile.path}' is not a file !`); - return; - } - if (!conf.tool) { - webviewPanel.webview.html = this.genHtmlCont(title, `Error: invalid toolchain type !`); + webviewPanel.webview.html = this.genHtmlCont(title, `Error: Invalid toolchain type !`); return; } @@ -616,10 +609,19 @@ class MapViewEditorProvider implements vscode.CustomTextEditorProvider { toolName = 'GCC_ARM'; break; default: - webviewPanel.webview.html = this.genHtmlCont(title, `Error: we not support this toolchain type: '${conf.tool}' !`); + webviewPanel.webview.html = this.genHtmlCont(title, `Error: We not support this toolchain type: '${conf.tool}' !`); return; } + // get map file + const defName = viewFile.noSuffixName + '.map'; + const mapFile = File.fromArray([viewFile.dir, conf.fileName || defName]); + + if (!mapFile.IsFile()) { + webviewPanel.webview.html = this.genHtmlCont(title, `Error: Not found file '${mapFile.path}' !`); + return; + } + // auto update when file changed try { From d714266e17bde35694b8caddadb2c60ed9d54266 Mon Sep 17 00:00:00 2001 From: null Date: Sun, 5 Dec 2021 23:42:25 +0800 Subject: [PATCH 47/48] v2.15.0 --- CHANGELOG.md | 31 +++++++++++++++++++++-------- README.md | 4 +++- package.json | 2 +- res/data/template.files.options.yml | 14 ++++++------- 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4538049..0ca2f7ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,25 +4,40 @@ *** -### [v2.15.0 RC1] -- 新增:向**项目依赖**视图增加一个**修改**按钮,允许以直接修改 yaml 配置文件的形式修改项目依赖 -- 新增:向**项目资源**视图增加一个**配置**按钮,允许为单个的文件或组增加任意编译选项,支持使用 glob 模式匹配源文件和组 -- 新增:在输出目录生成 .map.view 文件,打开即可显示 RAM/FLASH 资源使用视图(仅支持ARM和GCC工程) +### [v2.15.0] (**requirements: VsCode ^1.60.0**) +- 新增:向**项目属性**视图增加一个**修改**按钮,允许以直接修改 yaml 配置文件的形式修改其配置,[文档](https://docs.em-ide.com/#/zh-cn/project_deps) +- 新增:向**项目资源**视图增加一个配置按钮,允许**为单个的文件或组增加任意编译选项**,支持使用 glob 模式匹配源文件和组,[文档](https://docs.em-ide.com/#/zh-cn/project_manager?id=为源文件附加单独的编译选项) +- 新增:为 **虚拟文件夹**/**源文件** 增加修改路径选项,允许修改文件的路径(方便直接修改整个虚拟文件夹树以及其链接到的源文件) +- 新增:将烧录选项 `程序文件` 的文件选择器取消,改为输入框;允许一次烧录多个程序文件,**程序文件** 字段格式 '`[,addr][;...]`' +- 新增:增加全片擦除功能,`ctrl+shift+p` 打开命令面板,输入 `Erase Chip`,即可执行(某些烧录器可能不支持,则该命令将退化为普通的烧录命令) +- 新增:在 **项目资源** 树中增加 `Output Files` 目录,用于查看生成的编译产物; 同时增加 axf, elf 信息查看功能,点击 axf/elf 文件即可打开 +- 新增:增加文件右键菜单项:打开所在目录 +- 新增:支持 armcc 反汇编查看,通过编辑器右键菜单 `查看反汇编` 即可打开 +- 新增:鼠标悬停显示文件,文件夹数量(仅虚拟文件夹) +- 新增:支持通过编写外部 js 脚本来导入其他IDE项目文件中的文件树,宏,头文件等信息(方便导入 `SEGGER Embedded Studio`,`IAR For ARM` 等其他任意 IDE 的项目),[文档](https://docs.em-ide.com/#/zh-cn/project_manager?id=从其他-ide-项目导入源文件资源) +- 新增:在输出目录生成 .map.view 文件,打开即可显示 map 文件的资源统计视图(仅支持ARMCC/GCC工程),[文档](https://docs.em-ide.com/#/zh-cn/utility_functions?id=查看程序资源视图) - 新增:支持在线下载安装 Keil 芯片支持包,默认远程仓库地址:https://github.com/github0null/eide-cmsis-pack - 修复:CMSIS Config Wizard 在解析不符合要求的字符串类型时,出现误判 - 修复:删除 CMSIS 包之后,相应的 MCU 预定义宏被删除 +- **更改:调整某些配置的显示名称**,如 **项目依赖** 更改为 **项目属性** +- 更改:使用 Linux VT100 颜色代码添加更完备的编译输出日志高亮(**win10 以下的系统可能不支持**;可通过向插件配置 `Builder.AdditionalCommandLine` 添加 `-no-color` 关闭色彩输出) +- **更改:支持为 Armcc v5/v6 工具链单独设置编译器路径,同时保留旧的 MDK TOOLS.INI 设置方法** +- 更改:生成 *.obj 时,根据相对路径将 obj 生成至相应的文件夹树中(若有无法计算相对路径的文件,统一生成至 `obj` 目录) +- 优化:当烧录选项 `程序文件` 为空时,使用默认的程序文件路径(ui 上显示为 `${projectName}.hex`) +- 优化:允许带空格的虚拟文件夹命名 +- 优化:项目资源文件夹树排序显示 - 优化:读取完 JLink Device 列表后,删除临时文件 - 优化:调整构建工具的 Log 显示 -- 更改:生成 obj 时,根据相对路径将 obj 生成至相应的文件夹树中 -- **更改:支持为 Armcc v5/v6 工具链单独设置编译器路径,同时保留旧的 MDK TOOLS.INI 设置方法** +- 优化 CMSIS Wizard UI:使被禁用的子项表单控件无法被选中 +- 优化 CMSIS Wizard UI:调整布局,优化 vscode 主题颜色适配 +- 优化 完善 CMSIS Wizard 的语法支持程度 *** ### [v2.14.0] - 优化:增加一些编译器预定义宏 - 优化:优化 Builder Config UI,修复选项卡阴影区域显示不正常的问题 - 新增:支持显示源文件的头文件引用,默认开启,可在插件设置中关闭 -- 新增:增加 [CMSIS Configuration Wizard](https://arm-software.github.io/CMSIS_5/Pack/html/configWizard.html) 功能。 打开带有 CMSIS Config 格式的头文件,右键菜单选择 `CMSIS Configuration Wizard` 即可打开配置UI - ![preview](./img/cmsis_wizard_preview.png) +- 新增:增加 [CMSIS Configuration Wizard](https://arm-software.github.io/CMSIS_5/Pack/html/configWizard.html) 功能。 打开带有 CMSIS Config 格式的头文件,右键菜单选择 `CMSIS Configuration Wizard` 即可打开配置UI,[文档](https://docs.em-ide.com/#/zh-cn/cmsis_wizard) *** ### [v2.13.0] diff --git a/README.md b/README.md index 9ee3f40a..8f5d6723 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ ## 功能特性 🎉 -* 支持 8051,STM8,Cortex-M,RISC-V 项目 +* 支持开发 8051,STM8,Cortex-M,RISC-V 项目 * 支持导入 KEIL 项目 (仅支持 KEIL 5 及以上版本) * 支持安装标准的 KEIL 芯片支持包 (仅用于 Cortex-M 项目) * 提供丰富的项目模板方便快速开始项目 @@ -30,6 +30,8 @@ * 内置的串口监视器,一键打开串口 * 支持使用 Cppcheck 对项目进行静态检查 * 自动生成默认调试配置,为调试器插件 Cortex-debug / STM8-debug 生成默认配置 +* 支持编写 js 脚本来导入任意的 IDE 项目源文件资源 +* 内置多种实用工具,`CMSIS Config Wizard UI`, `反汇编查看`,`程序资源视图` ... *** diff --git a/package.json b/package.json index e0121156..12e95325 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "homepage": "https://github.com/github0null/eide/blob/master/README.md", "license": "MIT", "description": "A singlechip development environment for 8051/STM8/Cortex-M/RISC-V", - "version": "2.14.0", + "version": "2.15.0", "engines": { "vscode": "^1.60.0" }, diff --git a/res/data/template.files.options.yml b/res/data/template.files.options.yml index e1a75bc6..1c640b11 100644 --- a/res/data/template.files.options.yml +++ b/res/data/template.files.options.yml @@ -11,11 +11,11 @@ version: '1.0' # : # # examples: -# main.cpp: --cpp11 -Og ... -# src/*.c: -gnu -O2 ... -# src/lib/**/*.cpp: --cpp11 -Os ... -# !Application/*.c: -O0 -# '**/*.c': -O2 -gnu ... +# 'main.cpp': --cpp11 -Og ... +# 'src/*.c': -gnu -O2 ... +# 'src/lib/**/*.cpp': --cpp11 -Os ... +# '!Application/*.c': -O0 +# '**/*.c': -O2 -gnu ... # # For more syntax, please refer to: https://www.npmjs.com/package/micromatch # @@ -25,11 +25,11 @@ version: '1.0' # for source files with filesystem paths # files: -# test/**/test.c: --c99 +# './test/**/*.c': --c99 # # for source files with virtual paths # virtualPathFiles: -# test/**/*.c: --c99 +# 'virtual_folder/**/*.c': --c99 From 6f4ce87821e9e44d37fa081afc57d72203a2c37e Mon Sep 17 00:00:00 2001 From: null Date: Sun, 5 Dec 2021 23:44:03 +0800 Subject: [PATCH 48/48] Update .vscodeignore --- .vscodeignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.vscodeignore b/.vscodeignore index 6c898204..63be0a06 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -38,6 +38,7 @@ bin/builder/*.xml bin/builder/*.exe.config bin/tools docs +test # shell script *.sh