@@ -39,7 +39,7 @@ import rollbar from '@cmt/rollbar';
3939import * as telemetry from '@cmt/telemetry' ;
4040import { VariantManager } from '@cmt/kits/variant' ;
4141import * as nls from 'vscode-nls' ;
42- import { ConfigurationWebview } from '@cmt/ui/cacheView' ;
42+ import { ConfigurationWebview , IOption } from '@cmt/ui/cacheView' ;
4343import { enableFullFeatureSet , extensionManager , updateFullFeatureSet , setContextAndStore } from '@cmt/extension' ;
4444import { CMakeCommunicationMode , ConfigurationReader , OptionConfig , UseCMakePresets , checkConfigureOverridesPresent } from '@cmt/config' ;
4545import * as preset from '@cmt/presets/preset' ;
@@ -2461,6 +2461,192 @@ export class CMakeProject {
24612461 . then ( doc => void vscode . window . showTextDocument ( doc ) ) ;
24622462 }
24632463
2464+ private getPresetCacheVariableType ( option : IOption , presetCacheVariable : preset . CacheVarType | undefined ) : string {
2465+ if ( option . type === 'Bool' ) {
2466+ return 'BOOL' ;
2467+ }
2468+
2469+ if ( presetCacheVariable && typeof presetCacheVariable === 'object' && 'type' in presetCacheVariable && util . isString ( ( presetCacheVariable as any ) . type ) && ( presetCacheVariable as any ) . type . toUpperCase ( ) !== 'BOOL' ) {
2470+ return ( presetCacheVariable as any ) . type ;
2471+ }
2472+
2473+ return 'STRING' ;
2474+ }
2475+
2476+ private getPresetCacheVariableValue ( option : IOption ) : string {
2477+ return util . isBoolean ( option . value ) ? ( option . value ? 'TRUE' : 'FALSE' ) : String ( option . value ) ;
2478+ }
2479+
2480+ private getPresetCacheVariableRawValue ( cacheVariable : preset . CacheVarType | undefined ) : string | undefined {
2481+ if ( util . isString ( cacheVariable ) ) {
2482+ return cacheVariable ;
2483+ }
2484+
2485+ if ( cacheVariable === true ) {
2486+ return 'TRUE' ;
2487+ }
2488+
2489+ if ( cacheVariable && typeof cacheVariable === 'object' && 'value' in cacheVariable ) {
2490+ const value = cacheVariable . value ;
2491+ if ( util . isBoolean ( value ) ) {
2492+ return value ? 'TRUE' : 'FALSE' ;
2493+ }
2494+ if ( util . isString ( value ) ) {
2495+ return value ;
2496+ }
2497+ }
2498+
2499+ return undefined ;
2500+ }
2501+
2502+ private findPresetDefinitionByName ( name : string ) : preset . ConfigurePreset | undefined {
2503+ const userPreset = preset . userConfigurePresets ( this . folderPath , true ) . find ( configurePreset => configurePreset . name === name ) ;
2504+ if ( userPreset ) {
2505+ return userPreset ;
2506+ }
2507+ return preset . configurePresets ( this . folderPath , true ) . find ( configurePreset => configurePreset . name === name ) ;
2508+ }
2509+
2510+ private resolvePresetVariableOrigin (
2511+ presetName : string ,
2512+ variableName : string ,
2513+ visited : Set < string > = new Set ( )
2514+ ) : { presetName : string ; isUserPreset : boolean ; presetValue ?: string } | undefined {
2515+ if ( visited . has ( presetName ) ) {
2516+ return undefined ;
2517+ }
2518+ visited . add ( presetName ) ;
2519+
2520+ const configurePreset = this . findPresetDefinitionByName ( presetName ) ;
2521+ if ( ! configurePreset ) {
2522+ return undefined ;
2523+ }
2524+
2525+ const cacheVariable = configurePreset . cacheVariables ?. [ variableName ] ;
2526+ if ( cacheVariable !== undefined ) {
2527+ const isUserPreset = configurePreset . isUserPreset ?? configurePreset . __file ?. __path ?. endsWith ( 'CMakeUserPresets.json' ) ?? false ;
2528+ return {
2529+ presetName : configurePreset . name ,
2530+ isUserPreset,
2531+ presetValue : this . getPresetCacheVariableRawValue ( cacheVariable )
2532+ } ;
2533+ }
2534+
2535+ if ( configurePreset . inherits ) {
2536+ const parents = util . isString ( configurePreset . inherits ) ? [ configurePreset . inherits ] : configurePreset . inherits ;
2537+ if ( parents ) {
2538+ for ( const parent of parents ) {
2539+ const origin = this . resolvePresetVariableOrigin ( parent , variableName , visited ) ;
2540+ if ( origin ) {
2541+ return origin ;
2542+ }
2543+ }
2544+ }
2545+ }
2546+
2547+ return undefined ;
2548+ }
2549+
2550+ private async getCacheOptionPresetMetadata ( options : IOption [ ] ) : Promise < Map < string , { presetSource : string ; differsFromPresetValue ?: boolean } > > {
2551+ const metadata = new Map < string , { presetSource : string ; differsFromPresetValue ?: boolean } > ( ) ;
2552+ if ( ! this . useCMakePresets || ! this . configurePreset ) {
2553+ return metadata ;
2554+ }
2555+
2556+ const activePresetName = this . configurePreset . name ;
2557+ for ( const option of options ) {
2558+ const origin = this . resolvePresetVariableOrigin ( activePresetName , option . key ) ;
2559+ if ( ! origin ) {
2560+ continue ;
2561+ }
2562+
2563+ const sourceKind = origin . isUserPreset
2564+ ? localize ( 'preset.source.user' , 'User preset' )
2565+ : localize ( 'preset.source.project' , 'Project preset' ) ;
2566+
2567+ let differsFromPresetValue : boolean | undefined ;
2568+ if ( origin . presetValue !== undefined ) {
2569+ if ( option . type === 'Bool' ) {
2570+ differsFromPresetValue = util . isTruthy ( String ( option . value ) ) !== util . isTruthy ( origin . presetValue ) ;
2571+ } else {
2572+ differsFromPresetValue = String ( option . value ) !== origin . presetValue ;
2573+ }
2574+ }
2575+
2576+ metadata . set ( option . key , {
2577+ presetSource : `${ sourceKind } : ${ origin . presetName } ` ,
2578+ differsFromPresetValue
2579+ } ) ;
2580+ }
2581+
2582+ return metadata ;
2583+ }
2584+
2585+ private async updatePresetBackedCacheVariableOverrides ( dirtyOptions : IOption [ ] ) : Promise < void > {
2586+ if ( ! this . useCMakePresets || ! this . configurePreset || dirtyOptions . length === 0 ) {
2587+ return ;
2588+ }
2589+
2590+ const presetCacheVariables = this . configurePreset . cacheVariables ;
2591+ if ( ! presetCacheVariables ) {
2592+ return ;
2593+ }
2594+
2595+ const presetBackedOptions = dirtyOptions . filter ( option => Object . prototype . hasOwnProperty . call ( presetCacheVariables , option . key ) ) ;
2596+ if ( presetBackedOptions . length === 0 ) {
2597+ return ;
2598+ }
2599+
2600+ const userPresets = preset . getOriginalUserPresetsFile ( this . folderPath )
2601+ ?? { version : preset . getOriginalPresetsFile ( this . folderPath ) ?. version ?? 8 } ;
2602+ userPresets . configurePresets = userPresets . configurePresets ?? [ ] ;
2603+
2604+ const currentPreset = this . configurePreset ;
2605+ let targetPreset = currentPreset . isUserPreset
2606+ ? userPresets . configurePresets . find ( configurePreset => configurePreset . name === currentPreset . name )
2607+ : undefined ;
2608+
2609+ if ( ! targetPreset ) {
2610+ const defaultOverrideName = `${ currentPreset . name } __cacheEditorOverride` ;
2611+ let overrideName = defaultOverrideName ;
2612+ let suffix = 1 ;
2613+ const allPresetNames = new Set ( preset . allConfigurePresets ( this . folderPath , true ) . map ( configurePreset => configurePreset . name ) ) ;
2614+
2615+ while ( allPresetNames . has ( overrideName ) && ! userPresets . configurePresets . find ( configurePreset => configurePreset . name === overrideName ) ) {
2616+ overrideName = `${ defaultOverrideName } _${ suffix ++ } ` ;
2617+ }
2618+
2619+ targetPreset = userPresets . configurePresets . find ( configurePreset => configurePreset . name === overrideName ) ;
2620+ if ( ! targetPreset ) {
2621+ targetPreset = {
2622+ name : overrideName ,
2623+ hidden : true ,
2624+ inherits : currentPreset . name ,
2625+ cacheVariables : { }
2626+ } ;
2627+ userPresets . configurePresets . push ( targetPreset ) ;
2628+ }
2629+ }
2630+
2631+ targetPreset . cacheVariables = targetPreset . cacheVariables ?? { } ;
2632+
2633+ for ( const option of presetBackedOptions ) {
2634+ const presetCacheVariable = presetCacheVariables [ option . key ] ;
2635+ targetPreset . cacheVariables [ option . key ] = {
2636+ type : this . getPresetCacheVariableType ( option , presetCacheVariable ) ,
2637+ value : this . getPresetCacheVariableValue ( option )
2638+ } ;
2639+ }
2640+
2641+ this . presetsController . suppressWatcherReapply = true ;
2642+ await this . presetsController . updatePresetsFile ( userPresets , true , false ) ;
2643+ await this . presetsController . reapplyPresets ( ) ;
2644+
2645+ if ( targetPreset . name !== currentPreset . name ) {
2646+ await this . presetsController . setConfigurePreset ( targetPreset . name ) ;
2647+ }
2648+ }
2649+
24642650 /**
24652651 * Implementation of `cmake.EditCacheUI`
24662652 */
@@ -2472,9 +2658,10 @@ export class CMakeProject {
24722658 return 1 ;
24732659 }
24742660
2475- this . cacheEditorWebview = new ConfigurationWebview ( drv . cachePath , ( ) => {
2476- void this . configureInternal ( ConfigureTrigger . commandEditCacheUI , [ ] , ConfigureType . Cache ) ;
2477- } ) ;
2661+ this . cacheEditorWebview = new ConfigurationWebview ( drv . cachePath , async dirtyOptions => {
2662+ await this . updatePresetBackedCacheVariableOverrides ( dirtyOptions ) ;
2663+ await this . configureInternal ( ConfigureTrigger . commandEditCacheUI , [ ] , ConfigureType . Cache ) ;
2664+ } , async options => this . getCacheOptionPresetMetadata ( options ) ) ;
24782665 await this . cacheEditorWebview . initPanel ( ) ;
24792666
24802667 this . cacheEditorWebview . panel . onDidDispose ( ( ) => {
0 commit comments