diff --git a/package.json b/package.json index 736e09dd..0d0e219c 100644 --- a/package.json +++ b/package.json @@ -538,6 +538,16 @@ "category": "eide", "title": "Create gcc system stubs for project" }, + { + "command": "eide.project.generateClangdConfig", + "category": "eide", + "title": "%eide.project.generateClangdConfig%" + }, + { + "command": "eide.project.reload", + "category": "eide", + "title": "%eide.project.reload%" + }, { "command": "eide.debug.start", "category": "eide", @@ -1347,6 +1357,16 @@ "when": "viewItem == SOLUTION && view == cl.eide.view.projects", "group": "4_group@2" }, + { + "command": "eide.project.reload", + "when": "viewItem == SOLUTION && view == cl.eide.view.projects", + "group": "4_group@3" + }, + { + "command": "eide.project.generateClangdConfig", + "when": "viewItem == SOLUTION && view == cl.eide.view.projects", + "group": "4_group@4" + }, { "command": "_cl.eide.project.switchMode", "when": "viewItem == SOLUTION && view == cl.eide.view.projects", diff --git a/package.nls.json b/package.nls.json index 8ec3e8a9..b58d1dc0 100644 --- a/package.nls.json +++ b/package.nls.json @@ -21,6 +21,8 @@ "eide.project.save.all": "Save All Projects", "eide.project.active": "Active Project", "eide.project.close": "Close Project", + "eide.project.reload": "Reload Project", + "eide.project.generateClangdConfig": "Generate .clangd Config", "eide.project.show.commands": "Show Compiler CommandLine", "eide.project.switch.target": "Switch Target", "eide.project.build": "Build", diff --git a/package.nls.zh-CN.json b/package.nls.zh-CN.json index 9b506de8..c29ae74f 100644 --- a/package.nls.zh-CN.json +++ b/package.nls.zh-CN.json @@ -21,6 +21,8 @@ "eide.project.save.all": "保存所有项目", "eide.project.active": "设为活动", "eide.project.close": "关闭项目", + "eide.project.reload": "重新加载项目", + "eide.project.generateClangdConfig": "生成 .clangd 配置", "eide.project.show.commands": "查看生成的编译器命令行", "eide.project.switch.target": "切换目标", "eide.project.build": "构建", diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index a74e2f96..cd5f2ae9 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -140,7 +140,7 @@ import { jsonc } from 'jsonc'; import { SimpleUIConfig, SimpleUIConfigData_input, SimpleUIConfigData_options, SimpleUIConfigData_text, SimpleUIConfigData_table, SimpleUIConfigData_boolean, SimpleUIConfigData_divider, SimpleUIConfigData_tag } from "./SimpleUIDef"; import { StatusBarManager } from './StatusBarManager'; import { doMigration, detectProject } from './EIDEProjectMigration'; -import { onRegisterClangdProvider } from './clangdConfigProvider'; +import { onRegisterClangdProvider, generateClangdConfig } from './clangdConfigProvider'; enum TreeItemType { SOLUTION, @@ -3468,6 +3468,29 @@ export class ProjectExplorer implements CustomConfigurationProvider { GlobalEvent.emit('project.closed', uid); } + GenerateClangdConfig(item?: ProjTreeItem) { + const prj = this.getProjectByTreeItem(item); + if (prj == undefined) { + GlobalEvent.emit('msg', newMessage('Warning', 'No activated project !')); + return; + } + try { + generateClangdConfig(prj); + GlobalEvent.emit('msg', newMessage('Info', `.clangd config generated for '${prj.getProjectName()}'`)); + } catch (error) { + GlobalEvent.emit('msg', ExceptionToMessage(error, 'Warning')); + } + } + + async ReloadProject(item?: ProjTreeItem): Promise { + const prj = this.getProjectByTreeItem(item); + if (prj == undefined) { + GlobalEvent.emit('msg', newMessage('Warning', 'No activated project !')); + return; + } + await this.reloadProject(prj.getUid(), prj.getWorkspaceFile()); + } + SaveAll() { this.dataProvider.SaveAll(); } @@ -3564,7 +3587,7 @@ export class ProjectExplorer implements CustomConfigurationProvider { this.enableAutoSave(true); } - private async reloadProject(uid: string, workspaceFile: File): Promise { + async reloadProject(uid: string, workspaceFile: File): Promise { const idx = this.dataProvider.getIndexByProjectUid(uid); if (idx == -1) { diff --git a/src/clangdConfigProvider.ts b/src/clangdConfigProvider.ts index 62a37745..88843315 100644 --- a/src/clangdConfigProvider.ts +++ b/src/clangdConfigProvider.ts @@ -124,69 +124,70 @@ export async function onRegisterClangdProvider(prj: AbstractProject) { return; } - // ---------------------- - // setup clangd config - // ---------------------- try { - let cfg: any = {}; - const fclangd = File.fromArray([prj.getProjectRoot().path, '.clangd']); - if (fclangd.IsFile()) { - cfg = yaml.parse(fclangd.Read()); - } - if (!cfg['CompileFlags']) cfg['CompileFlags'] = {}; - if (!cfg['CompileFlags']['Add']) cfg['CompileFlags']['Add'] = [] - if (!cfg['CompileFlags']['Remove']) cfg['CompileFlags']['Remove'] = []; - // - cfg['CompileFlags']['CompilationDatabase'] = './' + File.ToUnixPath(prj.getOutputDir()); - const toolchain = prj.getToolchain(); - const gccLikePath = toolchain.getGccFamilyCompilerPathForCpptools('c'); - if (gccLikePath) { // clangd 仅兼容gcc的编译器 - cfg['CompileFlags']['Compiler'] = gccLikePath; - let clangdCompileFlags = (cfg['CompileFlags']['Add']); - let compilerArgs = prj.getCpptoolsConfig().cppCompilerArgs; - if (isGccFamilyToolchain(toolchain.name)) { - const tRoot = toolchain.getToolchainDir().path; - clangdCompileFlags = clangdCompileFlags.filter(p => !File.isSubPathOf(tRoot, p.substr(2))); - let li = getGccSystemSearchList(File.ToLocalPath(gccLikePath), ['-xc++'].concat(compilerArgs || [])); - if (li) { - li.forEach(p => { - clangdCompileFlags.push(`-I${File.normalize(p)}`); - }); - } - } else if (toolchain.name == 'LLVM_ARM') { - // nothing todo. This is llvm. - } else { - clangdCompileFlags.push(`-I${toolchain.getToolchainDir().path}/include`); - clangdCompileFlags.push(`-I${toolchain.getToolchainDir().path}/include/libcxx`); - } - // // add flags - // if (compilerArgs) - // compilerArgs.forEach(arg => clangdCompileFlags.push(arg)); - // // add user includes - // prj.getCpptoolsConfig().includePath - // .forEach(path => clangdCompileFlags.push(`-I${path}`)); - // // add user defines - // prj.getCpptoolsConfig().defines - // .forEach(d => clangdCompileFlags.push(`-D${d}`)); - // del repeat - cfg['CompileFlags']['Add'] = ArrayDelRepetition(clangdCompileFlags); - } - // 其他不受 clangd 支持的编译器要自行设置 -I -D - else if (toolchain.name == 'AC5' || toolchain.name == 'SDCC' || toolchain.name == 'GNU_SDCC_MCS51') { - const builderOpts = prj.getBuilderOptions(); - const prjConfig = prj.GetConfiguration(); - const compilerFlags: string[] = cfg['CompileFlags']['Add'] || []; - toolchain.getSystemIncludeList(builderOpts) - .forEach(p => compilerFlags.push(`-I"${p}"`)); - toolchain.getInternalDefines(prjConfig.config.toolchainConfig, builderOpts) - .forEach(d => compilerFlags.push(`-D"${d.name}=${d.value}"`)); - cfg['CompileFlags']['Add'] = ArrayDelRepetition(compilerFlags); - // 禁用所有诊断错误,因为 clangd 不支持这些编译器 - cfg['Diagnostics'] = { 'Suppress': '*' } - } - fclangd.Write(yaml.stringify(cfg)); + generateClangdConfig(prj); } catch (error) { GlobalEvent.log_error(error); } }); } + +export function generateClangdConfig(prj: AbstractProject): void { + let cfg: any = {}; + const fclangd = File.fromArray([prj.getProjectRoot().path, '.clangd']); + if (fclangd.IsFile()) { + cfg = yaml.parse(fclangd.Read()); + } + if (!cfg['CompileFlags']) cfg['CompileFlags'] = {}; + if (!cfg['CompileFlags']['Add']) cfg['CompileFlags']['Add'] = [] + if (!cfg['CompileFlags']['Remove']) cfg['CompileFlags']['Remove'] = []; + // + cfg['CompileFlags']['CompilationDatabase'] = './' + File.ToUnixPath(prj.getOutputDir()); + const toolchain = prj.getToolchain(); + const gccLikePath = toolchain.getGccFamilyCompilerPathForCpptools('c'); + if (gccLikePath) { // clangd 仅兼容gcc的编译器 + cfg['CompileFlags']['Compiler'] = gccLikePath; + let clangdCompileFlags = (cfg['CompileFlags']['Add']); + let compilerArgs = prj.getCpptoolsConfig().cppCompilerArgs; + if (isGccFamilyToolchain(toolchain.name)) { + const tRoot = toolchain.getToolchainDir().path; + clangdCompileFlags = clangdCompileFlags.filter(p => !File.isSubPathOf(tRoot, p.substr(2))); + let li = getGccSystemSearchList(File.ToLocalPath(gccLikePath), ['-xc++'].concat(compilerArgs || [])); + if (li) { + li.forEach(p => { + clangdCompileFlags.push(`-I${File.normalize(p)}`); + }); + } + } else if (toolchain.name == 'LLVM_ARM') { + // nothing todo. This is llvm. + } else { + clangdCompileFlags.push(`-I${toolchain.getToolchainDir().path}/include`); + clangdCompileFlags.push(`-I${toolchain.getToolchainDir().path}/include/libcxx`); + } + // // add flags + // if (compilerArgs) + // compilerArgs.forEach(arg => clangdCompileFlags.push(arg)); + // // add user includes + // prj.getCpptoolsConfig().includePath + // .forEach(path => clangdCompileFlags.push(`-I${path}`)); + // // add user defines + // prj.getCpptoolsConfig().defines + // .forEach(d => clangdCompileFlags.push(`-D${d}`)); + // del repeat + cfg['CompileFlags']['Add'] = ArrayDelRepetition(clangdCompileFlags); + } + // 其他不受 clangd 支持的编译器要自行设置 -I -D + else if (toolchain.name == 'AC5' || toolchain.name == 'SDCC' || toolchain.name == 'GNU_SDCC_MCS51') { + const builderOpts = prj.getBuilderOptions(); + const prjConfig = prj.GetConfiguration(); + const compilerFlags: string[] = cfg['CompileFlags']['Add'] || []; + toolchain.getSystemIncludeList(builderOpts) + .forEach(p => compilerFlags.push(`-I"${p}"`)); + toolchain.getInternalDefines(prjConfig.config.toolchainConfig, builderOpts) + .forEach(d => compilerFlags.push(`-D"${d.name}=${d.value}"`)); + cfg['CompileFlags']['Add'] = ArrayDelRepetition(compilerFlags); + // 禁用所有诊断错误,因为 clangd 不支持这些编译器 + cfg['Diagnostics'] = { 'Suppress': '*' } + } + fclangd.Write(yaml.stringify(cfg)); +} diff --git a/src/extension.ts b/src/extension.ts index dd92a4ea..600e5118 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -171,6 +171,8 @@ export async function activate(context: vscode.ExtensionContext) { subscriptions.push(vscode.commands.registerCommand('eide.project.genBuilderParams', (item) => projectExplorer.BuildSolution(item, { not_rebuild: true, onlyDumpBuilderParams: true }))); subscriptions.push(vscode.commands.registerCommand('eide.open.makelibs.cfg', (item) => projectExplorer.openLibsGeneratorConfig(item))); subscriptions.push(vscode.commands.registerCommand('eide.project.create_sys_stubs', (projuid) => projectExplorer.createSysStubs(projuid))); + subscriptions.push(vscode.commands.registerCommand('eide.project.generateClangdConfig', (item) => projectExplorer.GenerateClangdConfig(item))); + subscriptions.push(vscode.commands.registerCommand('eide.project.reload', (item) => projectExplorer.ReloadProject(item))); // operations bar subscriptions.push(vscode.commands.registerCommand('_cl.eide.project.historyRecord', () => projectExplorer.openHistoryRecords()));