Skip to content

The settings source generator emits incompatible code for VS settings renderer. #568

@kaheimri

Description

@kaheimri

We are aware this API is marked [Experimental("VSEXTPREVIEW_SETTINGS")], but the schema mismatch means the feature is currently unusable regardless of stability status.

Setting.FormattedString with SettingStringFormat.DirectoryPath generates invalid settingsRegistration.json"format": "directoryPath" not recognized by VS settings renderer.

Component

Microsoft.VisualStudio.Extensibility.JsonGenerators.Sdk (17.14.2098)

Description

When a Setting.FormattedString property is declared with SettingStringFormat.DirectoryPath, the source generator emits:

"format": "directoryPath"

The VS unified settings renderer does not recognize "directoryPath" as a valid format value and renders the setting as a plain text box instead of a folder picker. The correct schema, used by built-in extensions such as CMake and Copilot, requires two properties:

"format": "path",
"pathKind": "folder"

The root cause is that SettingStringFormat.DirectoryPath is initialized with the literal string "directoryPath":

// Microsoft.VisualStudio.Extensibility.Settings.SettingStringFormat
// Microsoft.VisualStudio.Extensibility.JsonGenerators.Sdk 17.14.2098

public static SettingStringFormat FilePath { get; } = new SettingStringFormat("filePath");
public static SettingStringFormat DirectoryPath { get; } = new SettingStringFormat("directoryPath");

// WriteJson passes the backing string directly to the JSON writer — no special handling
public override void WriteJson(JsonWriter writer, SettingStringFormat value, JsonSerializer serializer)
    => writer.WriteValue(value.value ?? "");

The generator serializes this value directly as the JSON format field via a JsonConverter whose WriteJson writes the backing string verbatim — no special handling. It also never emits "pathKind", so the picker type cannot be determined even if the format value were corrected. The same issue applies to SettingStringFormat.FilePath"filePath", which presumably requires "pathKind": "file".

Steps to reproduce

  1. Create an out-of-process VS extension targeting the VisualStudio.Extensibility SDK.
  2. Declare a Setting.FormattedString with SettingStringFormat.DirectoryPath:
[VisualStudioContribution]
internal static Setting.FormattedString MyDirectory { get; } =
    new("myDirectory", "My Directory", category,
        SettingStringFormat.DirectoryPath, defaultValue: string.Empty);
  1. Build the project and inspect the generated settingsRegistration.json.

Expected result

"myExtension.myDirectory": {
  "type": "string",
  "format": "path",
  "pathKind": "folder",
  ...
}

Actual result

"myExtension.myDirectory": {
  "type": "string",
  "format": "directoryPath",
  ...
}

The setting renders as a plain text box in the VS Options dialog instead of a folder browser.

Workaround

We needed to implement a post-build MSBuild task that patches the generated JSON, replacing "format": "directoryPath" with "format": "path" and injecting "pathKind": "folder". The post-build workaround and the comments documenting the SDK bug are visible here:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions