diff --git a/CHANGELOG.md b/CHANGELOG.md index 49f8d22e8..6c4a59635 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # What's New? +## 1.22 + +Bug Fixes: + +- Fix incorrect IntelliSense configuration when a `UTILITY` has source files. [#4404](https://github.com/microsoft/vscode-cmake-tools/issues/4404) + ## 1.21 Features: diff --git a/src/cpptools.ts b/src/cpptools.ts index efd4c5fc2..f3abfcd64 100644 --- a/src/cpptools.ts +++ b/src/cpptools.ts @@ -310,6 +310,27 @@ export function getIntelliSenseMode(cptVersion: cpptools.Version, compilerPath: } } +/** + * Try to find a target configuration with some populated properties. + * + * All targets get defaults for `compilerPath`, `compilerArgs`, and + * `compilerFragments`, even `UTILITY` targets defined with + * `add_custom_command()` that provide no other useful configuration, so if + * possible, return one with more than just those populated. + */ +function fallbackConfiguration(configurations: Map | undefined) { + if (!configurations) { + return undefined; + } + for (const item of configurations.values()) { + const { configuration: { includePath, defines, intelliSenseMode, standard} } = item; + if (includePath.length || defines.length || intelliSenseMode || standard) { + return item; + } + } + return configurations.values().next().value; +} + /** * The actual class that provides information to the cpptools extension. See * the `CustomConfigurationProvider` interface for information on how this class @@ -345,7 +366,7 @@ export class CppConfigurationProvider implements cpptools.CustomConfigurationPro if (this.activeTarget && configurations?.has(this.activeTarget)) { return configurations!.get(this.activeTarget); } else { - return configurations?.values().next().value; // Any value is fine if the target doesn't match + return fallbackConfiguration(configurations); } } diff --git a/test/unit-tests/cpptools.test.ts b/test/unit-tests/cpptools.test.ts index 77b6c6148..234f4b5d6 100644 --- a/test/unit-tests/cpptools.test.ts +++ b/test/unit-tests/cpptools.test.ts @@ -321,12 +321,21 @@ suite('CppTools tests', () => { name: 'cpptools-test2', sourceDirectory: smokeFolder, targets: [ + { + name: 'utilityTarget', + type: 'UTILITY', + fileGroups: [{ + sources: [sourceFile3], + isGenerated: false + }] + }, { name: 'target3', type: 'EXECUTABLE', fileGroups: [{ sources: [sourceFile3], isGenerated: false, + defines: ['DEFINE3'], // make this a more attractive fallback than utilityTarget compileCommandFragments: ['-DFRAGMENT3'], language: 'CXX' }] @@ -370,7 +379,8 @@ suite('CppTools tests', () => { // Verify the browsePath with a different folder. const configurations2 = await provider.provideConfigurations([uri3]); expect(configurations2.length).to.eq(1); - expect(configurations2[0].configuration.defines).to.be.empty; + expect(configurations2[0].configuration.defines.length).to.eq(1); + expect(configurations2[0].configuration.defines).to.contain('DEFINE3'); expect(configurations2[0].configuration.compilerFragments).to.contain('-DFRAGMENT3'); const browseConfig2 = await provider.provideFolderBrowseConfiguration(vscode.Uri.file(smokeFolder)); expect(browseConfig2?.browsePath.length).to.eq(1);