Change:
Tested on Insiders Build 1.65.0 and Build 1.64.2. If an extension's settings are viewed, the presentation order is respected, but _only if the "Search settings" bar is empty. If the search bar contains anything, including the name of the extension (matching all settings for that extension), the presentation order is alphabetical. Given that the presentation can still be controlled by the selected extension name in the left menu, it would seem logically possible to respect the sort ordering within an extension settings group. Examples: Following ordering (search area blank): ! Not following ordering: !
Verification steps: or write an extension with settings where the settings group and the individual settings use fields to determine the order. An example is at Also make the setting keys similar so that they can show up under the same search query. the extension, navigate to the Settings editor, and clear the search widget. that the settings for that extension are displayed in the expected order. a query to the search widget such that those extension settings still show up. that the filtered settings for that extension show up in the same order as in step 3.
Tested just now on LGTM

Discussion:
editPresentation?: EditPresentationTypes; defaultValueSource?: string | IExtensionInfo; isLanguageTagSetting?: boolean; <ins> categoryOrder?: number; categoryLabel?: string; </ins> } export interface IExtensionSetting extends ISetting {

import { ITextEditorModel } from 'vs/editor/common/services/resolverService'; import * as nls from 'vs/nls'; import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; <del> import { ConfigurationScope, Extensions, IConfigurationNode, IConfigurationPropertySchema, IConfigurationRegistry, IExtensionInfo, IRegisteredConfigurationPropertySchema, OVERRIDE_PROPERTY_REGEX } from 'vs/platform/configuration/common/configurationRegistry'; </del> <ins> import { ConfigurationScope, Extensions, IConfigurationNode, IConfigurationRegistry, IExtensionInfo, IRegisteredConfigurationPropertySchema, OVERRIDE_PROPERTY_REGEX } from 'vs/platform/configuration/common/configurationRegistry'; </ins> import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { Registry } from 'vs/platform/registry/common/platform'; import { EditorModel } from 'vs/workbench/common/editor/editorModel';

}); } <ins> private compareTwoNullableNumbers(a: number | undefined, b: number | undefined): number { const aOrMax = a ?? Number.MAX_SAFE_INTEGER; const bOrMax = b ?? Number.MAX_SAFE_INTEGER; if (aOrMax < bOrMax) { return -1; } else if (aOrMax > bOrMax) { return 1; } else { return 0; } } </ins> filterSettings(filter: string, groupFilter: IGroupFilter, settingMatcher: ISettingMatcher): ISettingMatch[] { const allGroups = this.filterGroups;

} filterMatches.sort((a, b) => { <del> // Sort by match type if the match types are not equal. // The priority of the match type is given by the SettingMatchType enum. // If they're equal, fall back to the "stable sort" counter score. </del> if (a.matchType !== b.matchType) { <ins> // Sort by match type if the match types are not the same. // The priority of the match type is given by the SettingMatchType enum. </ins> return b.matchType - a.matchType; } else { <ins> // The match types are the same. if (a.setting.extensionInfo && b.setting.extensionInfo && a.setting.extensionInfo.id === b.setting.extensionInfo.id) { // These settings belong to the same extension. if (a.setting.categoryLabel !== b.setting.categoryLabel && (a.setting.categoryOrder !== undefined || b.setting.categoryOrder !== undefined) && a.setting.categoryOrder !== b.setting.categoryOrder) { // These two settings don't belong to the same category and have different category orders. return this.compareTwoNullableNumbers(a.setting.categoryOrder, b.setting.categoryOrder); } else if (a.setting.categoryLabel === b.setting.categoryLabel && (a.setting.order !== undefined || b.setting.order !== undefined) && a.setting.order !== b.setting.order) { // These two settings belong to the same category, but have different orders. return this.compareTwoNullableNumbers(a.setting.order, b.setting.order); } } // In the worst case, go back to lexicographical order. </ins> return b.score - a.score; } });

result.push(settingsGroup); } const configurationSettings: ISetting[] = []; <del> for (const setting of [...settingsGroup.sections[settingsGroup.sections.length - 1].settings, ...this.parseSettings(config.properties, config.extensionInfo)]) { </del> <ins> for (const setting of [...settingsGroup.sections[settingsGroup.sections.length - 1].settings, ...this.parseSettings(config)]) { </ins> if (!seenSettings[setting.key]) { configurationSettings.push(setting); seenSettings[setting.key] = true;

return result; } <del> private parseSettings(settingsObject: { [path: string]: IConfigurationPropertySchema }, extensionInfo?: IExtensionInfo): ISetting[] { </del> <ins> private parseSettings(config: IConfigurationNode): ISetting[] { </ins> const result: ISetting[] = []; <ins> const settingsObject = config.properties; const extensionInfo = config.extensionInfo; // Try using the title if the category id wasn't given // (in which case the category id is the same as the extension id) const categoryLabel = config.extensionInfo?.id === config.id ? config.title : config.id; const categoryOrder = config.order; </ins> for (const key in settingsObject) { const prop = settingsObject[key]; if (this.matchesScope(prop)) {

editPresentation: prop.editPresentation, order: prop.order, defaultValueSource, <del> isLanguageTagSetting </del> <ins> isLanguageTagSetting, categoryLabel, categoryOrder </ins> }); } }