diff --git a/CHANGELOG.md b/CHANGELOG.md
index babeb73a..c8b524c0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,18 @@ All notable version changes will be recorded in this file.
***
+### [v3.10.8] update
+
+**New**:
+ - `Project Resource`: Add `Symbol Table` virtual file in `Output Files`, click it to show `elf symbols` (support 'armcc', 'gcc', 'iar').
+ - `Builder Options` : Add `X/O Base`, `R/O Base`, `R/W Base` options for armcc, and allow import them from keil project.
+
+**Optimize**:
+ - `launch.json Generator`: Don't force override 'svdPath' in launch.json config.
+ - `Project Resource`: Show promt when remove a filesystem source dir.
+
+***
+
### [v3.10.7] revision
**Fix**:
diff --git a/lang/arm.v5.verify.json b/lang/arm.v5.verify.json
index 25538164..1c89a879 100644
--- a/lang/arm.v5.verify.json
+++ b/lang/arm.v5.verify.json
@@ -432,6 +432,24 @@
false
]
},
+ "xo-base": {
+ "markdownDescription": "X/O Base",
+ "description.zh-cn": "X/O Base",
+ "size": "small",
+ "type": "string"
+ },
+ "ro-base": {
+ "markdownDescription": "R/O Base",
+ "description.zh-cn": "R/O Base",
+ "size": "small",
+ "type": "string"
+ },
+ "rw-base": {
+ "markdownDescription": "R/W Base",
+ "description.zh-cn": "R/W Base",
+ "size": "small",
+ "type": "string"
+ },
"misc-controls": {
"markdownDescription": "Other Linker Options",
"description.zh-cn": "链接器附加选项",
@@ -448,4 +466,4 @@
}
}
}
-}
+}
\ No newline at end of file
diff --git a/lang/arm.v6.verify.json b/lang/arm.v6.verify.json
index 9924b4b8..cea1eaf6 100644
--- a/lang/arm.v6.verify.json
+++ b/lang/arm.v6.verify.json
@@ -370,6 +370,24 @@
false
]
},
+ "xo-base": {
+ "markdownDescription": "X/O Base",
+ "description.zh-cn": "X/O Base",
+ "size": "small",
+ "type": "string"
+ },
+ "ro-base": {
+ "markdownDescription": "R/O Base",
+ "description.zh-cn": "R/O Base",
+ "size": "small",
+ "type": "string"
+ },
+ "rw-base": {
+ "markdownDescription": "R/W Base",
+ "description.zh-cn": "R/W Base",
+ "size": "small",
+ "type": "string"
+ },
"misc-controls": {
"markdownDescription": "Other Linker Options",
"description.zh-cn": "链接器附加选项",
diff --git a/package.json b/package.json
index 3a1aafa2..893810c0 100644
--- a/package.json
+++ b/package.json
@@ -35,7 +35,7 @@
"homepage": "https://em-ide.com",
"license": "MIT",
"description": "A mcu development environment for 8051/AVR/STM8/Cortex-M/RISC-V",
- "version": "3.10.7",
+ "version": "3.10.8",
"preview": false,
"engines": {
"vscode": "^1.67.0"
@@ -603,6 +603,22 @@
"light": "./res/icon/Import_16x.svg"
}
},
+ {
+ "command": "_cl.eide.project.symbol_view.sort_by_addr",
+ "title": "Sort By Address"
+ },
+ {
+ "command": "_cl.eide.project.symbol_view.sort_by_size",
+ "title": "Sort By Size"
+ },
+ {
+ "command": "_cl.eide.project.symbol_view.disp_hide_no_sized",
+ "title": "Hide no-size Symbols"
+ },
+ {
+ "command": "_cl.eide.project.symbol_view.disp_show_all",
+ "title": "Show All Symbols"
+ },
{
"command": "_cl.eide.project.cppcheck.check_all",
"title": "%eide.project.run.cppcheck%"
@@ -1121,6 +1137,26 @@
"command": "_cl.eide.project.source.show_cmsis_config_wizard",
"group": "commands",
"when": "resourceLangId =~ /^c$|^cpp$/ && !config.EIDE.Option.DisableEditorContextMenu"
+ },
+ {
+ "command": "_cl.eide.project.symbol_view.sort_by_addr",
+ "group": "commands",
+ "when": "resourceExtname =~ /\\.elf-symbols$/ && cl.eide.projectActived"
+ },
+ {
+ "command": "_cl.eide.project.symbol_view.sort_by_size",
+ "group": "commands",
+ "when": "resourceExtname =~ /\\.elf-symbols$/ && cl.eide.projectActived"
+ },
+ {
+ "command": "_cl.eide.project.symbol_view.disp_hide_no_sized",
+ "group": "commands",
+ "when": "resourceExtname =~ /\\.elf-symbols$/ && cl.eide.projectActived"
+ },
+ {
+ "command": "_cl.eide.project.symbol_view.disp_show_all",
+ "group": "commands",
+ "when": "resourceExtname =~ /\\.elf-symbols$/ && cl.eide.projectActived"
}
],
"explorer/context": [
@@ -1486,7 +1522,7 @@
{
"id": "elf.info",
"aliases": [
- "Gnu Elf Info"
+ "GNU ELF Info"
],
"extensions": [
".elf.info"
diff --git a/res/data/option.mapper.json b/res/data/option.mapper.json
index 4fcc52ef..dc0dfb7d 100644
--- a/res/data/option.mapper.json
+++ b/res/data/option.mapper.json
@@ -180,6 +180,15 @@
"true": "1",
"false": "0"
}
+ },
+ "xo-base": {
+ "keilName": "pXoBase"
+ },
+ "ro-base": {
+ "keilName": "TextAddressRange"
+ },
+ "rw-base": {
+ "keilName": "DataAddressRange"
}
}
}
@@ -390,6 +399,15 @@
"true": "1",
"false": "0"
}
+ },
+ "xo-base": {
+ "keilName": "pXoBase"
+ },
+ "ro-base": {
+ "keilName": "TextAddressRange"
+ },
+ "rw-base": {
+ "keilName": "DataAddressRange"
}
}
}
diff --git a/res/icon/Table_16x.svg b/res/icon/Table_16x.svg
new file mode 100644
index 00000000..93284dae
--- /dev/null
+++ b/res/icon/Table_16x.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/CodeBuilder.ts b/src/CodeBuilder.ts
index 959cd72b..5ac52c1b 100644
--- a/src/CodeBuilder.ts
+++ b/src/CodeBuilder.ts
@@ -891,6 +891,7 @@ export class ARMCodeBuilder extends CodeBuilder {
let scatterFilePath: string = config.compileConfig.scatterFilePath;
switch (toolchain.name) {
+
// 'armcc' can select whether use custom linker file
case 'AC5':
case 'AC6':
@@ -935,6 +936,28 @@ export class ARMCodeBuilder extends CodeBuilder {
// set linker script
options.linker['link-scatter'] = ldFileList;
+ // for armcc
+ if (['AC5', 'AC6'].includes(toolchain.name)) {
+
+ // if no scatter, will use X/O Base, R/O Base options
+ if (ldFileList.length == 0) {
+
+ let xo_base = options.linker['xo-base']?.trim();
+ let ro_base = options.linker['ro-base']?.trim();
+ let rw_base = options.linker['rw-base']?.trim();
+
+ let ld_flag: string[] = [];
+
+ if (xo_base) ld_flag.push(`--xo-base ${xo_base}`);
+ if (ro_base) ld_flag.push(`--ro-base ${ro_base} --entry ${ro_base}`);
+ if (rw_base) ld_flag.push(`--rw-base ${rw_base}`);
+
+ ld_flag.push('--entry Reset_Handler', '--first __Vectors');
+
+ options.linker['misc-controls'] = ld_flag.join(' ') + ' ' + (options.linker['misc-controls'] || '');
+ }
+ }
+
if (options.afterBuildTasks === undefined) {
options.afterBuildTasks = [];
}
diff --git a/src/DebugConfigGenerator.ts b/src/DebugConfigGenerator.ts
index d438082a..a79f1c09 100644
--- a/src/DebugConfigGenerator.ts
+++ b/src/DebugConfigGenerator.ts
@@ -167,8 +167,7 @@ class CortexDebugConfigProvider extends IDebugConfigProvider {
// setup svd file, if existed
const device = prj.GetPackManager().getCurrentDevInfo();
- debugConfig.svdFile = undefined;
- if (device && device.svdPath) {
+ if (device && device.svdPath && debugConfig.svdFile == undefined) {
debugConfig.svdFile = prj.ToRelativePath(device.svdPath) || device.svdPath;
}
diff --git a/src/EIDEProject.ts b/src/EIDEProject.ts
index f3930800..4d574cd9 100644
--- a/src/EIDEProject.ts
+++ b/src/EIDEProject.ts
@@ -838,6 +838,10 @@ export abstract class AbstractProject implements CustomConfigurationProvider, Pr
return this.GetRootDir();
}
+ public getExecutablePathWithoutSuffix(): string {
+ return [this.getRootDir().path, this.getOutputDir(), this.getProjectName()].join(File.sep);
+ }
+
public getUid(): string {
const miscInfo = this.GetConfiguration().config.miscInfo;
if (miscInfo.uid == undefined) miscInfo.uid = md5(`${this.getEideDir().path}-${Date.now()}`);
@@ -1170,18 +1174,27 @@ export abstract class AbstractProject implements CustomConfigurationProvider, Pr
}
}
+ /**
+ * get output dir top root name. like: `build`
+ */
+ getOutputRoot(): string {
+ return this.GetConfiguration().getOutDirRoot();
+ }
+
+ /**
+ * get output dir name. like: 'build\Debug'
+ */
getOutputDir(): string {
return this.GetConfiguration().getOutDir();
}
+ /**
+ * get output dir full file system path. like: 'c:\xxx\xxx\proj\build\Debug'
+ */
getOutputFolder(): File {
return new File(this.ToAbsolutePath(this.GetConfiguration().getOutDir()));
}
- getOutputRoot(): string {
- return this.GetConfiguration().getOutDirRoot();
- }
-
getEideDir(): File {
return this.eideDir;
}
@@ -1974,7 +1987,7 @@ export abstract class AbstractProject implements CustomConfigurationProvider, Pr
this.registerBuiltinVar('ProjectName', () => this.GetConfiguration().config.name);
this.registerBuiltinVar('ConfigName', () => this.GetConfiguration().config.mode);
this.registerBuiltinVar('ProjectRoot', () => this.getRootDir().path);
- this.registerBuiltinVar('ExecutableName', () => [this.getRootDir().path, this.GetConfiguration().getOutDir(), this.GetConfiguration().config.name].join(File.sep));
+ this.registerBuiltinVar('ExecutableName', () => this.getExecutablePathWithoutSuffix());
}
private RegisterEvent(): void {
diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts
index fbb830cd..e90d88ae 100644
--- a/src/EIDEProjectExplorer.ts
+++ b/src/EIDEProjectExplorer.ts
@@ -62,6 +62,7 @@ import {
view_str$prompt$unresolved_deps,
view_str$prompt$prj_location,
view_str$prompt$src_folder_must_be_a_child_of_root,
+ view_str$prompt$removeSrcDir,
view_str$project$folder_type_virtual_desc,
view_str$project$folder_type_fs_desc,
view_str$msg$err_ewt_hash,
@@ -70,7 +71,9 @@ import {
view_str$prompt$need_reload_project,
view_str$prompt$needReloadToUpdateEnv,
getLocalLanguageType,
- LanguageIndexs
+ LanguageIndexs,
+ txt_yes,
+ txt_no
} from './StringTable';
import { CodeBuilder, BuildOptions } from './CodeBuilder';
import { ExceptionToMessage, newMessage } from './Message';
@@ -174,9 +177,11 @@ function getTreeItemTypeName(typ: TreeItemType): string {
type GroupRegion = 'PACK' | 'Components' | 'ComponentItem';
interface TreeItemValue {
- key?: string; // name will be show in label
- alias?: string; // alias name will be show in label
- value: string | File; // if TreeItem refer to a file, the value type is 'File'
+ label?: string; // UI item label, if it's null, item label is '${keyAlias || key} : ${value}' or '${value}'
+ key?: string; // key name will be show in label
+ keyAlias?: string; // key's alias name will be show in label
+ value: string | File; // if TreeItem refer to a file, the value type must be 'File'
+ isVirtualFile?: boolean;
contextVal?: string;
tooltip?: string | vscode.MarkdownString;
icon?: string;
@@ -260,8 +265,12 @@ export class ProjTreeItem extends vscode.TreeItem {
if (val.value instanceof File) {
this.label = val.value.name;
} else {
- const lableName: string | undefined = val.alias ? val.alias : val.key;
- this.label = lableName ? (`${lableName} : ${val.value}`) : val.value;
+ const name = val.keyAlias || val.key;
+ this.label = name ? `${name} : ${val.value}` : val.value;
+ }
+
+ if (val.label) {
+ this.label = val.label;
}
// setup unique id
@@ -827,7 +836,14 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco
return this.prjList[index];
}
- getIndexByProject(uid: string): number {
+ getProjectByUid(uid: string): AbstractProject | undefined {
+ const idx = this.getIndexByProjectUid(uid);
+ if (idx != -1) {
+ return this.GetProjectByIndex(idx);
+ }
+ }
+
+ getIndexByProjectUid(uid: string): number {
return this.prjList.findIndex(prj => prj.getUid() == uid);
}
@@ -1106,7 +1122,7 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco
if (cConfig.isKeyEnable(key) && !excludeKeys.includes(key)) {
iList.push(new ProjTreeItem(TreeItemType.COMPILE_CONFIGURATION_ITEM, {
key: key,
- alias: cConfig.GetKeyDescription(key),
+ keyAlias: cConfig.GetKeyDescription(key),
value: cConfig.getKeyValue(key),
tooltip: newMarkdownString([
`${cConfig.GetKeyDescription(key)}`,
@@ -1128,7 +1144,7 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco
if (model.isKeyEnable(key)) {
iList.push(new ProjTreeItem(TreeItemType.UPLOAD_OPTION_ITEM, {
key: key,
- alias: model.GetKeyDescription(key),
+ keyAlias: model.GetKeyDescription(key),
value: model.getKeyValue(key),
tooltip: newMarkdownString([
`${model.GetKeyDescription(key)}`,
@@ -1174,7 +1190,7 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco
iList.push(new ProjTreeItem(TreeItemType.SETTINGS_ITEM, {
key: 'name',
value: config.config.name,
- alias: view_str$settings$prj_name,
+ keyAlias: view_str$settings$prj_name,
tooltip: newMarkdownString(`**${view_str$settings$prj_name}**: \`${config.config.name}\``),
projectIndex: element.val.projectIndex
}));
@@ -1183,7 +1199,7 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco
iList.push(new ProjTreeItem(TreeItemType.SETTINGS_ITEM, {
key: 'outDir',
value: File.normalize(config.config.outDir),
- alias: view_str$settings$outFolderName,
+ keyAlias: view_str$settings$outFolderName,
tooltip: newMarkdownString(`**${view_str$settings$outFolderName}**: \`${config.config.outDir}\``),
projectIndex: element.val.projectIndex
}));
@@ -1192,7 +1208,7 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco
iList.push(new ProjTreeItem(TreeItemType.SETTINGS_ITEM, {
key: 'project.env',
value: 'object {...}',
- alias: view_str$settings$prjEnv,
+ keyAlias: view_str$settings$prjEnv,
tooltip: view_str$settings$prjEnv,
projectIndex: element.val.projectIndex
}));
@@ -1359,11 +1375,11 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco
// output folder
case TreeItemType.OUTPUT_FOLDER:
{
+ // put output files
const outFolder = project.getOutputFolder();
if (outFolder.IsDir()) {
const fList = outFolder.GetList([AbstractProject.buildOutputMatcher], File.EXCLUDE_ALL_FILTER);
fList.forEach((file) => {
- const fsize = file.getSize();
iList.push(new ProjTreeItem(TreeItemType.OUTPUT_FILE_ITEM, {
value: file,
collapsibleState: vscode.TreeItemCollapsibleState.None,
@@ -1376,6 +1392,29 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco
}));
});
}
+
+ // put virtual views
+ {
+ // Symbol Table
+ // - not support sdcc, keil_c51 now !
+ if (!['Keil_C51', 'SDCC'].includes(project.getToolchain().name)) {
+
+ let vFile = File.fromArray([project.getRootDir().path, `${project.getUid()}.elf-symbols`]);
+ iList.push(new ProjTreeItem(TreeItemType.OUTPUT_FILE_ITEM, {
+ label: `Symbol Table`,
+ value: vFile,
+ isVirtualFile: true,
+ collapsibleState: vscode.TreeItemCollapsibleState.None,
+ projectIndex: element.val.projectIndex,
+ tooltip: `Symbols Of Program`,
+ icon: `Table_16x.svg`
+ }));
+ if (VirtualDocument.instance().hasDocument(vFile.path) == false) {
+ VirtualDocument.instance().registerDocumentGetter(vFile.path,
+ (uri, args) => this.printProjectBinarySymbols(uri, args[0], args[1]));
+ }
+ }
+ }
}
break;
// output file item
@@ -1507,6 +1546,441 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco
return iList;
}
+ /*
+ 文档:https://sourceware.org/binutils/docs-2.39/binutils.html#nm
+ 下面说明符号类型:对于每一个符号来说,其类型如果是小写的,则表明该符号是local的;大写则表明该符号是global(external)的。
+ A 该符号的值是绝对的,在以后的链接过程中,不允许进行改变。这样的符号值,常常出现在中断向量表中,例如用符号来表示各个中断向量函数在中断向量表中的位置。
+ B 该符号的值出现在非初始化数据段(bss)中。例如,在一个文件中定义全局static int test。则该符号test的类型为b,位于bss section中。其值表示该符号在bss段中的偏移。一般而言,bss段分配于RAM中
+ C 该符号为common。common symbol是未初始话数据段。该符号没有包含于一个普通section中。只有在链接过程中才进行分配。符号的值表示该符号需要的字节数。例如在一个c文件中,定义int test,并且该符号在别的地方会被引用,则该符号类型即为C。否则其类型为B。
+ D 该符号位于初始话数据段中。一般来说,分配到data section中。例如定义全局int baud_table[5] = {9600, 19200, 38400, 57600, 115200},则会分配于初始化数据段中。
+ G 该符号也位于初始化数据段中。主要用于small object提高访问small data object的一种方式。
+ I 该符号是对另一个符号的间接引用。
+ N 该符号是一个debugging符号。
+ R 该符号位于只读数据区。例如定义全局const int test[] = {123, 123};则test就是一个只读数据区的符号。注意在cygwin下如果使用gcc直接编译成MZ格式时,源文件中的test对应_test,并且其符号类型为D,即初始化数据段中。但是如果使用m6812-elf-gcc这样的交叉编译工具,源文件中的test对应目标文件的test,即没有添加下划线,并且其符号类型为R。一般而言,位于rodata section。值得注意的是,如果在一个函数中定义const char *test = “abc”, const char test_int = 3。使用nm都不会得到符号信息,但是字符串“abc”分配于只读存储器中,test在rodata section中,大小为4。
+ S 符号位于非初始化数据区,用于small object。
+ T 该符号位于代码区text section。
+ U 该符号在当前文件中是未定义的,即该符号的定义在别的文件中。例如,当前文件调用另一个文件中定义的函数,在这个被调用的函数在当前就是未定义的;但是在定义它的文件中类型是T。但是对于全局变量来说,在定义它的文件中,其符号类型为C,在使用它的文件中,其类型为U。
+ V 该符号是一个weak object。
+ W The symbol is a weak symbol that has not been specifically tagged as a weak object symbol. 未明确指定的弱链接符号;同链接的其他对象文件中有它的定义就用上,否则就用一个系统特别指定的默认值。
+ - 该符号是a.out格式文件中的stabs symbol。
+ ? 该符号类型没有定义
+ */
+ private convGnuSymbolType2ReadableString(typ: string): string {
+
+ let typeStr: string | undefined;
+
+ switch (typ.toLowerCase()) {
+ case 'a':
+ typeStr = 'ABS'
+ break;
+ case 'b':
+ typeStr = 'BSS'
+ break;
+ case 'c':
+ typeStr = 'COMMON'
+ break;
+ case 'd':
+ typeStr = 'DATA'
+ break;
+ case 'i':
+ typeStr = `Indirect Reference`
+ break;
+ case 'n':
+ typeStr = `Debug`
+ break;
+ case 'r':
+ typeStr = `DATA (Read Only)`
+ break;
+ case 't':
+ typeStr = `TEXT`
+ break;
+ case 'u':
+ typeStr = `Undefined`
+ break;
+ case 'v':
+ typeStr = `Weak`
+ break;
+ case 'w':
+ typeStr = `Weak (unspecified)`
+ break;
+ default:
+ break;
+ }
+
+ if (typeStr) {
+ if (typ.toLowerCase() == typ) { // is a lowercase word
+ typeStr += ' (Local)'
+ }
+ }
+
+ if (typeStr) {
+ return `${typ}: ${typeStr}`;
+ }
+
+ return typ;
+ }
+
+ private printProjectBinarySymbols(uri: vscode.Uri,
+ sortType?: 'addr' | 'size', dispType?: 'hide_no_sized' | 'show_all'): Promise {
+
+ if (sortType == undefined) {
+ sortType = 'addr';
+ }
+
+ if (dispType == undefined) {
+ dispType = 'hide_no_sized';
+ }
+
+ return new Promise((resolve) => {
+
+ const uid = new File(uri.fsPath).noSuffixName;
+ const prj = this.getProjectByUid(uid);
+
+ if (prj == undefined) {
+ resolve(`Error: Not found project '${uid}' !`);
+ return;
+ }
+
+ try {
+
+ const toolchain = prj.getToolchain();
+ const toolchainPrefix = toolchain.getToolchainPrefix ? toolchain.getToolchainPrefix() : '';
+
+ let elfpath = '';
+ let elftool = '';
+ let elfcmds = [''];
+ let elfsort = false; // elftool has sorted ?
+
+ let staMatcher: RegExp | undefined;
+ let endMatcher: RegExp | undefined;
+ let symMatcher: RegExp | undefined;
+ let symTypConv: ((type: string) => string) | undefined;
+ let locMatcher: RegExp | undefined;
+
+ // sometimes a long line has been truncated, like this:
+ // 4183: Temperature_Sampling_NVIC_Configuration
+ // 0x800f4d1 5 Code Gb 0x38
+ // we need match and recover them !
+ let truncatStaMatcher: RegExp | undefined;
+ let truncatEndMatcher: RegExp | undefined;
+
+ switch (toolchain.name) {
+ // armcc fmt:
+ // # Symbol Name Value Bind Sec Type Vis Size
+ case 'AC5':
+ case 'AC6':
+ elfpath = prj.getExecutablePathWithoutSuffix() + '.axf';
+ elftool = [toolchain.getToolchainDir().path, 'bin', `fromelf${exeSuffix()}`].join(File.sep);
+ elfcmds = ['--text', '-s', elfpath];
+ staMatcher = /\(SHT_SYMTAB\)/
+ endMatcher = /^\*\* Section/
+ truncatStaMatcher = /^\s*\d+\s+(?:[^\s]+)\s*$/i
+ truncatEndMatcher = /^\s*0x[0-9a-f]+\s+/i
+ symMatcher = /^\s*\d+\s+(?[^\s]+)\s+(?0x[0-9a-f]+)\s+(?:[^\s]+)\s+(?:[^\s]+)\s+(?[^\s]+)\s+(?:[^\s]+)(?\s+[^\s]+)?/i
+ break;
+ // iar fmt:
+ // # Name Value Sec Type Bd Size Group Other
+ case 'IAR_ARM':
+ elfpath = prj.getExecutablePathWithoutSuffix() + '.out';
+ elftool = [toolchain.getToolchainDir().path, 'bin', `ielfdumparm${exeSuffix()}`].join(File.sep);
+ elfcmds = ['-s', '.symtab', elfpath];
+ symMatcher = /^\s*\d+:\s+(?[^\s]+)\s+(?0x[0-9a-f]+)\s+(?:[^\s]+)\s+(?[^\s]+\s+[^\s]+)(?\s+0x[0-9a-f]+)?/i;
+ truncatStaMatcher = /^\s*\d+:\s+(?:[^\s]+)\s*$/i
+ truncatEndMatcher = /^\s*0x[0-9a-f]+\s+/i
+ break;
+ case 'IAR_STM8':
+ elfpath = prj.getExecutablePathWithoutSuffix() + '.out';
+ elftool = [toolchain.getToolchainDir().path, 'stm8', 'bin', `ielfdumpstm8${exeSuffix()}`].join(File.sep);
+ elfcmds = ['-s', '.symtab', elfpath];
+ symMatcher = /^\s*\d+:\s+(?[^\s]+)\s+(?0x[0-9a-f]+)\s+(?:[^\s]+)\s+(?[^\s]+\s+[^\s]+)(?\s+0x[0-9a-f]+)?/i;
+ truncatStaMatcher = /^\s*\d+:\s+(?:[^\s]+)\s*$/i
+ truncatEndMatcher = /^\s*0x[0-9a-f]+\s+/i
+ break;
+ case 'GCC':
+ case 'RISCV_GCC':
+ case 'ANY_GCC':
+ elfpath = prj.getExecutablePathWithoutSuffix() + '.elf';
+ elftool = [toolchain.getToolchainDir().path, 'bin', `${toolchainPrefix}nm${exeSuffix()}`].join(File.sep);
+ elfcmds = sortType == 'size' ? ['-l', '-S', '--size-sort', elfpath] : ['-ln', '-S', elfpath];
+ elfsort = true;
+ symMatcher = /^(?[0-9a-f]+)\s+(?[0-9a-f]+\s+)?(?\w)\s+(?[^\s]+)\s+(?.*)/i;
+ symTypConv = (t) => this.convGnuSymbolType2ReadableString(t)
+ break;
+ default:
+ throw new Error(`Not support symbol view for '${toolchain.name}' !`);
+ }
+
+ if (!File.IsFile(elfpath)) {
+ throw new Error(`Not found elf file: '${elfpath}', please build your project !`);
+ }
+
+ if (!File.IsFile(elftool)) {
+ throw new Error(`Not found elf tool: '${elftool}' !`);
+ }
+
+ let textLines = child_process.execFileSync(elftool, elfcmds).toString().split(/\r\n|\n/);
+
+ // filter lines
+ // notes:
+ // - will contain the line that matched by 'staMatcher'
+ // - Not contain the line that matched by 'endMatcher'
+ if (staMatcher) {
+
+ let matchedLines: string[] = [];
+ let started = false;
+
+ for (const line of textLines) {
+
+ if (!started && staMatcher.test(line)) {
+ started = true;
+ }
+
+ if (started) {
+
+ if (matchedLines.length > 0 &&
+ endMatcher && endMatcher.test(line)) {
+ break;
+ }
+
+ matchedLines.push(line);
+ }
+ }
+
+ textLines = matchedLines;
+ }
+
+ // if no pattern, output raw text
+ if (symMatcher === undefined) {
+ resolve(textLines.join(os.EOL));
+ return;
+ }
+
+ const tableHeader: string[] = ['Address', 'Size', 'Type', 'Symbol Name', 'Location'];
+
+ let resultLines: string[][] = [];
+
+ let col_addr_maxLen = tableHeader[0].length;
+ let col_size_maxLen = tableHeader[1].length;
+ let col_type_maxLen = tableHeader[2].length;
+ let col_name_maxLen = tableHeader[3].length;
+ let col_loca_maxLen = tableHeader[4].length;
+
+ let sym_cur_file_location: string | undefined;
+
+ let sym_count = 0;
+
+ for (let i = 0; i < textLines.length; i++) {
+
+ let line = textLines[i];
+
+ if (locMatcher) {
+ const m = locMatcher.exec(line);
+ if (m && m.groups) {
+ sym_cur_file_location = m.groups['loca']?.trim();
+ }
+ }
+
+ if (truncatStaMatcher && truncatEndMatcher) {
+ let nxtLine = i + 1 < textLines.length ? textLines[i + 1] : undefined;
+ if (nxtLine &&
+ truncatStaMatcher.test(line) && truncatEndMatcher.test(nxtLine)) {
+ line = line + nxtLine;
+ i++;
+ }
+ }
+
+ const m = symMatcher.exec(line);
+ if (!(m && m.groups)) { // no matched
+ continue;
+ }
+
+ let addr = m.groups['addr']?.trim();
+ let size = m.groups['size']?.trim();
+ let type = m.groups['type']?.trim();
+ let name = m.groups['name']?.trim();
+ let loca = m.groups['loca']?.trim();
+
+ if (!addr || !name) {
+ continue;
+ }
+
+ sym_count++;
+
+ if (type && symTypConv) {
+ type = symTypConv(type);
+ }
+
+ // symbol name is a source file ?
+ if (/\.(?:c|cpp|cxx|c\+\+|cc|s|asm)$/i.test(name)) {
+ sym_cur_file_location = name;
+ continue;
+ }
+
+ size = size || '--';
+ type = type || '--';
+ loca = loca || sym_cur_file_location || '--';
+
+ if (dispType == 'hide_no_sized' && size == '--') {
+ continue; // ignore no-size symbols
+ }
+
+ col_addr_maxLen = addr.length > col_addr_maxLen ? addr.length : col_addr_maxLen;
+ col_size_maxLen = size.length > col_size_maxLen ? size.length : col_size_maxLen;
+ col_type_maxLen = type.length > col_type_maxLen ? type.length : col_type_maxLen;
+ col_name_maxLen = name.length > col_name_maxLen ? name.length : col_name_maxLen;
+ col_loca_maxLen = loca.length > col_loca_maxLen ? loca.length : col_loca_maxLen;
+
+ resultLines.push([addr, size, type, name, loca]);
+ }
+
+ // sort lines
+ if (!elfsort) {
+
+ if (sortType == 'addr') {
+
+ resultLines = resultLines.sort((a1, a2) => {
+ const addr_1 = parseInt(a1[0], 16);
+ const addr_2 = parseInt(a2[0], 16);
+ return addr_1 - addr_2;
+ });
+ }
+
+ else if (sortType == 'size') {
+
+ let notSizeSyms: string[][] = [];
+ let hasSizeSyms: string[][] = [];
+
+ resultLines.forEach(sym => {
+ if (sym[1].startsWith('--')) {
+ notSizeSyms.push(sym);
+ } else {
+ hasSizeSyms.push(sym);
+ }
+ });
+
+ hasSizeSyms = hasSizeSyms.sort((a1, a2) => {
+ const size_1 = parseInt(a1[1], 16);
+ const size_2 = parseInt(a2[1], 16);
+ return size_1 - size_2;
+ });
+
+ resultLines = notSizeSyms.concat(hasSizeSyms);
+ }
+ }
+
+ // dump result
+
+ let headerLines = [
+ '',
+ 'ELF Symbols',
+ ` - Tool: '${elftool}'`,
+ ` - Cmds: '${elfcmds.join(' ')}'`,
+ ` - Symbol Count: ${sym_count}`,
+ ''
+ ];
+
+ let outputLines: string[] = headerLines;
+
+ // make header
+ {
+ outputLines.push(
+ `--${''.padEnd(col_addr_maxLen, '-')}-` +
+ `--${''.padEnd(col_size_maxLen, '-')}-` +
+ `--${''.padEnd(col_type_maxLen, '-')}-` +
+ `--${''.padEnd(col_name_maxLen, '-')}-` +
+ `--${''.padEnd(col_loca_maxLen, '-')}-`);
+
+ outputLines.push(
+ `| ${tableHeader[0].padEnd(col_addr_maxLen)} ` +
+ `| ${tableHeader[1].padEnd(col_size_maxLen)} ` +
+ `| ${tableHeader[2].padEnd(col_type_maxLen)} ` +
+ `| ${tableHeader[3].padEnd(col_name_maxLen)} ` +
+ `| ${tableHeader[4].padEnd(col_loca_maxLen)} `);
+
+ outputLines.push(
+ `--${''.padEnd(col_addr_maxLen, '-')}-` +
+ `--${''.padEnd(col_size_maxLen, '-')}-` +
+ `--${''.padEnd(col_type_maxLen, '-')}-` +
+ `--${''.padEnd(col_name_maxLen, '-')}-` +
+ `--${''.padEnd(col_loca_maxLen, '-')}-`);
+ }
+
+ for (let i = 1; i < resultLines.length; i++) {
+
+ outputLines.push(
+ `| ${resultLines[i][0].padEnd(col_addr_maxLen)} ` +
+ `| ${resultLines[i][1].padEnd(col_size_maxLen)} ` +
+ `| ${resultLines[i][2].padEnd(col_type_maxLen)} ` +
+ `| ${resultLines[i][3].padEnd(col_name_maxLen)} ` +
+ `| ${resultLines[i][4].padEnd(col_loca_maxLen)} `);
+ }
+
+ outputLines.push('');
+
+ resolve(outputLines.join(os.EOL));
+
+ //
+ // @deprecated Because this lib is too slow
+ //
+
+ // let maxLen = 0;
+ // for (const l of headerLines) {
+ // if (l.length > maxLen) maxLen = l.length;
+ // }
+
+ // for (let i = 1; i < headerLines.length; i++) {
+ // headerLines[i] = headerLines[i].padEnd(maxLen);
+ // }
+
+ // const tableCfg: TxtTable.TableUserConfig = {
+
+ // header: {
+ // alignment: 'center',
+ // content: headerLines.join('\n')
+ // },
+
+ // drawHorizontalLine: (idx, rowCount) => idx <= 2 || idx === rowCount,
+
+ // columns: {
+ // 0: { width: col_addr_maxLen },
+ // 1: { width: col_size_maxLen },
+ // 2: { width: col_type_maxLen },
+ // 3: { width: col_name_maxLen },
+ // 4: { width: col_loca_maxLen }
+ // },
+
+ // border: {
+ // topBody: `─`,
+ // topJoin: `┬`,
+ // topLeft: `┌`,
+ // topRight: `┐`,
+
+ // bottomBody: `─`,
+ // bottomJoin: `┴`,
+ // bottomLeft: `└`,
+ // bottomRight: `┘`,
+
+ // bodyLeft: `│`,
+ // bodyRight: `│`,
+ // bodyJoin: `│`,
+
+ // joinBody: `─`,
+ // joinLeft: `├`,
+ // joinRight: `┤`,
+ // joinJoin: `┼`
+ // }
+ // };
+
+ // const result = TxtTable.table(resultLines, tableCfg);
+
+ // resolve(result);
+
+ } catch (error) {
+ resolve('Error: ' + (error).message);
+ }
+ });
+ }
+
private async _OpenProject(workspaceFilePath: string): Promise {
const wsFile: File = new File(workspaceFilePath);
@@ -2489,10 +2963,14 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco
prjCompileOption.floatingPointHardware = keilCompileConf.floatingPointHardware || 'none';
prjCompileOption.useCustomScatterFile = keilCompileConf.useCustomScatterFile;
prjCompileOption.storageLayout = keilCompileConf.storageLayout;
+
if (keilCompileConf.scatterFilePath) {
prjCompileOption.scatterFilePath =
baseInfo.rootFolder.ToRelativePath(keilCompileConf.scatterFilePath) || keilCompileConf.scatterFilePath;
+ } else { // if no scatter, will use X/O Base, R/O Base options, make scatterFilePath empty
+ prjCompileOption.scatterFilePath = '';
}
+
// import builder options
const toolchain = ToolchainManager.getInstance().getToolchain('ARM', keilCompileConf.toolchain);
const opts = mergeBuilderOpts(toolchain.getDefaultConfig(), keilCompileConf.optionsGroup[keilCompileConf.toolchain]);
@@ -3202,7 +3680,7 @@ export class ProjectExplorer implements CustomConfigurationProvider {
private reloadProject(uid: string, workspaceFile: File) {
- const idx = this.dataProvider.getIndexByProject(uid);
+ const idx = this.dataProvider.getIndexByProjectUid(uid);
if (idx == -1) {
GlobalEvent.emit('msg', newMessage('Error', `Project '${uid}' is not actived !`));
return;
@@ -3485,7 +3963,7 @@ export class ProjectExplorer implements CustomConfigurationProvider {
}
for (const path in diag_res) {
- const uri = vscode.Uri.parse(File.ToUri(path));
+ const uri = vscode.Uri.file(path);
cc_diags.set(uri, diag_res[path]);
}
}
@@ -4046,11 +4524,17 @@ export class ProjectExplorer implements CustomConfigurationProvider {
}
async RemoveSrcDir(item: ProjTreeItem) {
- const prj = this.dataProvider.GetProjectByIndex(item.val.projectIndex);
- if (item.val.obj instanceof File) {
- prj.GetConfiguration().RemoveSrcDir(item.val.obj.path);
- } else {
- GlobalEvent.emit('error', new Error('remove source root failed !'));
+
+ if (!(item.val.obj instanceof File)) {
+ return;
+ }
+
+ const srcDir = item.val.obj;
+
+ const answer = await vscode.window.showInformationMessage(view_str$prompt$removeSrcDir.replace('{}', srcDir.path), txt_yes, txt_no);
+ if (answer == txt_yes) {
+ const prj = this.dataProvider.GetProjectByIndex(item.val.projectIndex);
+ prj.GetConfiguration().RemoveSrcDir(srcDir.path);
}
}
@@ -4701,7 +5185,7 @@ export class ProjectExplorer implements CustomConfigurationProvider {
if (mRes && mRes.length > 5) {
diagnosticCnt += 1; /* increment cnt */
const fpath = prj.ToAbsolutePath(mRes[pattern.file]);
- const uri = vscode.Uri.parse(File.ToUri(fpath));
+ const uri = vscode.Uri.file(fpath);
const diags = Array.from(this.cppcheck_diag.get(uri) || []);
const line = parseInt(mRes[pattern.line]);
const col = parseInt(mRes[pattern.column]);
@@ -5734,7 +6218,7 @@ export class ProjectExplorer implements CustomConfigurationProvider {
if (ProjTreeItem.isFileItem(item.type)) {
const file = item.val.value;
- const vsUri = vscode.Uri.parse(file.ToUri());
+
let isPreview = true;
if (this.prev_click_info &&
@@ -5755,9 +6239,15 @@ export class ProjectExplorer implements CustomConfigurationProvider {
// 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 });
+ if (item.val.isVirtualFile) {
+ const uri = vscode.Uri.parse(VirtualDocument.instance().getUriByPath(file.path));
+ VirtualDocument.instance().updateDocument(file.path);
+ vscode.window.showTextDocument(uri, { preview: isPreview });
+ } else {
+ /* We need use 'vscode.open' command, not 'showTextDocument' API,
+ * because API can't open bin file */
+ vscode.commands.executeCommand('vscode.open', vscode.Uri.file(file.path), { preview: isPreview });
+ }
} catch (error) {
GlobalEvent.emit('msg', ExceptionToMessage(error, 'Warning'));
@@ -5787,7 +6277,7 @@ export class ProjectExplorer implements CustomConfigurationProvider {
if (!fromelf.IsFile())
throw new Error(`Not found '${fromelf.path}' !`);
cont = child_process
- .execFileSync(fromelf.path, ['--text', '-e', binFile.path])
+ .execFileSync(fromelf.path, ['--text', '-v', binFile.path])
.toString();
} catch (error) {
const err = error;
diff --git a/src/KeilXmlParser.ts b/src/KeilXmlParser.ts
index a366ea38..9e423c99 100644
--- a/src/KeilXmlParser.ts
+++ b/src/KeilXmlParser.ts
@@ -572,7 +572,7 @@ class KeilSettingMapper {
const objGroup = domainObj[groupName];
const option = objGroup.properties[key];
if (option) {
- const value = option.enum[typeof val === 'boolean' ? val.toString() : val];
+ const value = option.enum ? option.enum[typeof val === 'boolean' ? val.toString() : val] : val;
if (value !== undefined) {
const keilCategory = TargetOption[this.mapper.keilName];
keilCategory[objGroup.keilName][option.keilName] = value;
@@ -592,6 +592,11 @@ class KeilSettingMapper {
if (keilGroup && keilGroup[option.keilName] !== undefined) {
const keilValue = keilGroup[option.keilName];
+
+ if (option.enum == undefined) {
+ return keilValue;
+ }
+
for (const opKey in option.enum) {
if (option.enum[opKey] === keilValue) {
if (opKey === 'true') {
@@ -962,7 +967,7 @@ class ARMParser extends KeilParser {
}
}
- //set current
+ // set current
const toolchain = prj.getToolchain();
const mapper = new KeilSettingMapper(toolchain.name);
const options: any = compileModel.getOptions(eidePath, prjConfig.config);
@@ -975,8 +980,12 @@ class ARMParser extends KeilParser {
if (armAdsObj.LDads) {
const LDads = armAdsObj.LDads;
LDads.umfTarg = config.useCustomScatterFile ? '0' : '1';
- const absPath = prj.ToAbsolutePath(config.scatterFilePath);
- LDads.ScatterFile = this.ToRelativePath(absPath);
+ if (config.scatterFilePath) {
+ const absPath = prj.ToAbsolutePath(config.scatterFilePath);
+ LDads.ScatterFile = this.ToRelativePath(absPath);
+ } else {
+ LDads.ScatterFile = '';
+ }
}
const info = armAdsObj.ArmAdsMisc;
diff --git a/src/ProblemMatcher.ts b/src/ProblemMatcher.ts
index 0e012a19..82abdf20 100644
--- a/src/ProblemMatcher.ts
+++ b/src/ProblemMatcher.ts
@@ -40,7 +40,7 @@ function parseLogLines(file: File): string[] {
});
} catch (error) {
- GlobalEvent.emit('msg', ExceptionToMessage(error, 'Hidden'));
+ // nothing todo
}
return ccLogLines;
diff --git a/src/StringTable.ts b/src/StringTable.ts
index ad15d4ad..dfb160f5 100644
--- a/src/StringTable.ts
+++ b/src/StringTable.ts
@@ -360,24 +360,6 @@ export const switch_workspace_hint = [
//--------------- env ---------------
-/*
- "desc.task.cmd.env.target_name": "项目名称",
- "desc.task.cmd.env.project_root": "项目根目录",
- "desc.task.cmd.env.output_dir": "编译输出目录",
- "desc.task.cmd.env.builer_folder": "构建器可执行文件目录",
- "desc.task.cmd.env.toolchain_root": "工具链根目录",
- "desc.task.cmd.env.compiler_prefix": "编译器前缀,例如:arm-none-eabi-",
- "desc.task.cmd.env.compiler_folder": "编译器可执行文件目录",
-
- "desc.task.cmd.env.target_name": "Project name",
- "desc.task.cmd.env.project_root": "Project root folder",
- "desc.task.cmd.env.output_dir": "Build output folder",
- "desc.task.cmd.env.builer_folder": "Builder executable file's folder",
- "desc.task.cmd.env.toolchain_root": "Toolchain root folder",
- "desc.task.cmd.env.compiler_prefix": "Compiler prefix, like: arm-none-eabi-",
- "desc.task.cmd.env.compiler_folder": "Compiler executable file's folder",
-*/
-
export const view_str$env_desc$project_name = [
`项目名称`,
`Project name`
@@ -415,6 +397,11 @@ export const view_str$env_desc$compiler_folder = [
//---------------Other---------------
+export const view_str$prompt$removeSrcDir = [
+ `从项目中移除源文件夹 '{}' ?`,
+ `Remove source folder '{}' from current project ?`
+][langIndex];
+
export const view_str$prompt$needReloadToUpdateEnv = [
`需要重启插件以刷新内置的环境变量,立即重启插件?`,
`We need relaunch plug-in to refresh internal environment variables, relaunch now ?`
diff --git a/src/VirtualDocsProvider.ts b/src/VirtualDocsProvider.ts
index fbf8bb4d..a8fe6181 100644
--- a/src/VirtualDocsProvider.ts
+++ b/src/VirtualDocsProvider.ts
@@ -27,17 +27,22 @@ import { File } from '../lib/node-utility/File';
let _instance: VirtualDocument | undefined;
+export type VirtualDocumentContentGetter = (uri: vscode.Uri, ...args: any[]) => Promise;
+
export class VirtualDocument implements vscode.TextDocumentContentProvider {
public static scheme = 'eide';
private onDidChangeEmitter: vscode.EventEmitter;
- private docsMap: Map;
+
+ private docsMap: Map;
+ private docsGetterArgs: Map;
onDidChange: vscode.Event;
private constructor() {
this.docsMap = new Map();
+ this.docsGetterArgs = new Map();
this.onDidChangeEmitter = new vscode.EventEmitter();
this.onDidChange = this.onDidChangeEmitter.event;
}
@@ -47,18 +52,58 @@ export class VirtualDocument implements vscode.TextDocumentContentProvider {
return _instance;
}
- updateDocument(path: string, content: string) {
- this.docsMap.set(path, content);
+ hasDocument(path: string): boolean {
+ return this.docsMap.has(path);
+ }
+
+ registerDocumentGetter(path: string, getter: VirtualDocumentContentGetter, ...getterArgs: any[]) {
+ this.docsMap.set(path, getter);
+ this.docsGetterArgs.set(path, getterArgs);
+ }
+
+ updateDocument(path: string, content?: string | VirtualDocumentContentGetter, ...getterArgs: any[]) {
+
+ if (content) {
+ this.docsMap.set(path, content);
+ } else {
+ if (!this.docsMap.has(path)) {
+ return; // not has this file and not file content, exit
+ }
+ }
+
+ this.docsGetterArgs.set(path, getterArgs);
+
this.onDidChangeEmitter.fire(vscode.Uri.parse(this.getUriByPath(path)));
}
+ removeDocument(path: string) {
+ this.docsMap.delete(path);
+ this.docsGetterArgs.delete(path);
+ this.onDidChangeEmitter.fire(vscode.Uri.parse(this.getUriByPath(path)));
+ }
+
+ getLastGetterArgs(path: string): any[] {
+ return this.docsGetterArgs.get(path) || [];
+ }
+
getUriByPath(path: string): string {
return `${VirtualDocument.scheme}://${File.ToNoProtocolUri(path)}`;
}
provideTextDocumentContent(uri: vscode.Uri, token: vscode.CancellationToken): vscode.ProviderResult {
- if (this.docsMap.has(uri.fsPath)) {
- return this.docsMap.get(uri.fsPath);
+ const getter = this.docsMap.get(uri.fsPath);
+ if (getter) {
+ if (typeof getter == 'string') {
+ return getter;
+ } else {
+ return vscode.window.withProgress({
+ location: vscode.ProgressLocation.Notification,
+ title: `Provide Text Document`
+ }, async (progress) => {
+ progress.report({ message: `${uri.fsPath}` });
+ return await getter(uri, this.docsGetterArgs.get(uri.fsPath) || []);
+ });
+ }
}
}
}
diff --git a/src/extension.ts b/src/extension.ts
index 7ab228ed..dd8413f2 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -172,6 +172,17 @@ export async function activate(context: vscode.ExtensionContext) {
subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.import.ext.source.struct', (item) => projectExplorer.ImportSourceFromExtProject(item)));
subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.source.modify.exclude_list', (item) => projectExplorer.openYamlConfig(item, 'src-exc-cfg')));
+ // symbol view editor commands
+ const virtDoc = VirtualDocument.instance();
+ subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.symbol_view.sort_by_addr',
+ (url) => virtDoc.updateDocument(url.fsPath, undefined, 'addr', virtDoc.getLastGetterArgs(url.fsPath)[1])));
+ subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.symbol_view.sort_by_size',
+ (url) => virtDoc.updateDocument(url.fsPath, undefined, 'size', virtDoc.getLastGetterArgs(url.fsPath)[1])));
+ subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.symbol_view.disp_hide_no_sized',
+ (url) => virtDoc.updateDocument(url.fsPath, undefined, virtDoc.getLastGetterArgs(url.fsPath)[0], 'hide_no_sized')));
+ subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.symbol_view.disp_show_all',
+ (url) => virtDoc.updateDocument(url.fsPath, undefined, virtDoc.getLastGetterArgs(url.fsPath)[0], 'show_all')));
+
// 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)));
diff --git a/src/utility.ts b/src/utility.ts
index f13a81a1..8ac09de2 100644
--- a/src/utility.ts
+++ b/src/utility.ts
@@ -26,7 +26,6 @@ import * as vscode from 'vscode';
import * as crypto from 'crypto';
import * as child_process from 'child_process';
import * as fs from 'fs';
-
import * as os from 'os';
import { WorkspaceManager } from "./WorkspaceManager";