Change:
I guess this a regression from Have workspace setting like below Reload the window :bug: you get change in which is a spread of those compact settings <img width="1512" alt="Screenshot 2023-09-28 at 10 29 54" src=""
I actually thought this was intentional and have pushed the change to branch.
There should not be migration happening in this case right?
I would suggest to check the new value and write only if it is changed.
Sounds look. Looking into this atm.
Resolved the settings changing in scenarios where migration is not needed, but in scenarios where migration is needed, the above change still happens. Ends up looking like this: Digging into it further, this is because doesn't have the concept of anything outside of it's current scope (in this case, ), seems to find the setting multiple times for each language. Not sure if there is a better way to handle the migrations but would appreciate some thoughts/insight - some of the more complex examples in are still a tad different from what we want to accomplish here.
I think you are doing the right thing here. The scenario you are hitting here is a limitation with the api. This is true with all editor settings migrations so it is not new with your migration. I would recommend you to go with your change ie., do migration only when value has changed. Filed separate issue to fix this in the update method - - I would prefer to fix this in next milestone because 1. It is not a regression 2. It is not a simple fix to do and therefore risky to do in the endgame.
To confirm, even though value is migrated to each language independently, the effective value is correct and will be the migrated value. I mean, the value of for and languages will be
Yes - original override with is unchanged, but the new settings written are changed properly from boolean to respective enum.
closing and deferring rest of issue to
repro: setting is this: should end up like this without duplicating the settings: example with multiple: expected to turn into:
Found following bug while verifying -

Discussion:
} }); <del> // Code Actions on Save registerEditorSettingMigration('codeActionsOnSave', (value, read, write) => { if (value && typeof value === 'object') { const newValue = {} as any; for (const entry of Object.entries(value)) { if (typeof entry[1] === 'boolean') { newValue[entry[0]] = entry[1] ? 'explicit' : 'never'; } else { newValue[entry[0]] = entry[1]; } } write(`codeActionsOnSave`, newValue); } }); </del> <ins> // // Code Actions on Save // registerEditorSettingMigration('codeActionsOnSave', (value, read, write) => { // 	if (value && typeof value === 'object') { // 		const newValue = {} as any; // 		for (const entry of Object.entries(value)) { // 			if (typeof entry[1] === 'boolean') { // 				newValue[entry[0]] = entry[1] ? 'explicit' : 'never'; // 			} else { // 				newValue[entry[0]] = entry[1]; // 			} // 		} // 		write(`codeActionsOnSave`, newValue); // 	} // }); </ins>

this._welcomeMessage = new ChatWelcomeMessageModel(this, content); } <del> return requests.map((raw: ISerializableChatRequestData) => { const parsedRequest = typeof raw.message === 'string' ? this.getParsedRequestFromString(raw.message) : reviveParsedChatRequest(raw.message); const request = new ChatRequestModel(this, parsedRequest, raw.providerRequestId); if (raw.response || raw.responseErrorDetails) { const agent = raw.agent && this.chatAgentService.getAgents().find(a => a.id === raw.agent!.id); // TODO do something reasonable if this agent has disappeared since the last session request.response = new ChatResponseModel(raw.response ?? [new MarkdownString(raw.response)], this, agent, true, raw.isCanceled, raw.vote, raw.providerRequestId, raw.responseErrorDetails, raw.followups); } return request; }); </del> <ins> try { return requests.map((raw: ISerializableChatRequestData) => { const parsedRequest = typeof raw.message === 'string' ? this.getParsedRequestFromString(raw.message) : reviveParsedChatRequest(raw.message); const request = new ChatRequestModel(this, parsedRequest, raw.providerRequestId); if (raw.response || raw.responseErrorDetails) { const agent = raw.agent && this.chatAgentService.getAgents().find(a => a.id === raw.agent!.id); // TODO do something reasonable if this agent has disappeared since the last session request.response = new ChatResponseModel(raw.response ?? [new MarkdownString(raw.response)], this, agent, true, raw.isCanceled, raw.vote, raw.providerRequestId, raw.responseErrorDetails, raw.followups); } return request; }); } catch (error) { this.logService.error('Failed to parse chat data', error); return []; } </ins> } private getParsedRequestFromString(message: string): IParsedChatRequest { // TODO These offsets won't be used, but chat replies need to go through the parser as well <del> const parts = [new ChatRequestTextPart(new OffsetRange(1, message.length), { startColumn: 1, startLineNumber: 1, endColumn: 1, endLineNumber: 1 }, message)]; </del> <ins> const parts = [new ChatRequestTextPart(new OffsetRange(0, message.length), { startColumn: 1, startLineNumber: 1, endColumn: 1, endLineNumber: 1 }, message)]; </ins> return { text: message, parts