Auto-generate ConfigurationSchema.json for JSON IntelliSense#10139
Auto-generate ConfigurationSchema.json for JSON IntelliSense#10139
Conversation
Add schema generation for appsettings.json IntelliSense when a client library has ClientSettings. The schema includes well-known client names under 'Clients' (SCM) or 'AzureClients' (Azure) sections, with $ref to shared credential/options definitions and allOf for client-specific option extensions. Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com> Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/555ac5bb-bd9c-4d73-90ca-f2922cf55fa5
Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com> Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/555ac5bb-bd9c-4d73-90ca-f2922cf55fa5
|
|
||
| // Determine if Azure or SCM based on the options base type namespace. | ||
| var optionsBaseType = ScmCodeModelGenerator.Instance.TypeFactory.ClientPipelineApi.ClientPipelineOptionsType; | ||
| bool isAzure = optionsBaseType.Namespace?.StartsWith("Azure", StringComparison.Ordinal) == true; |
There was a problem hiding this comment.
@copilot we shouldn't have anything related to Azure in the base emitter.
There was a problem hiding this comment.
Removed the Azure-specific namespace detection. Generate() now always uses "Clients" and "options" as defaults, with sectionName/optionsRef parameters that a derived emitter can override if needed. Fixed in 3541fb5.
Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com> Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/555ac5bb-bd9c-4d73-90ca-f2922cf55fa5
…rator The base emitter should not contain Azure-specific code. Removed the namespace-based Azure detection and made Generate() always use "Clients" and "options" as defaults, with parameters allowing overrides by derived emitters. Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com> Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/78f8c1a0-1d00-4e19-89d1-e9090dc2aeab
Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com> Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/7703f03f-8937-43a3-b716-e0e5f8090658
|
@copilot why didn't the regen show a diff since we don't have a ConfigurationSchema.json checked in for the Test Project? |
commit: |
Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/54e740be-2cdd-4b28-9516-7744e0fcf1dc Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com>
I hadn't run Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
But why didn't the Regen check step fail on the diff then? |
|
| "type": "string" | ||
| }, | ||
| "Credential": { | ||
| "$ref": "#/definitions/credential" |
There was a problem hiding this comment.
Added a BuildDefinitions() method that generates the definitions section with credential (authentication configuration with Type property) and options (base ClientPipelineOptions properties including NetworkTimeout and RetryPolicy). All $ref pointers now resolve correctly. Fixed in 27184ed.
| /// Generates a ConfigurationSchema.json file for JSON IntelliSense support in appsettings.json. | ||
| /// The schema defines well-known client names and their configuration properties. | ||
| /// </summary> | ||
| internal static class ConfigurationSchemaGenerator |
There was a problem hiding this comment.
@copilot we need to handle the options type inheriting from the core type. Here is an example using Azure options https://github.com/Azure/azure-sdk-for-net/pull/57548/changes
Note we will have a separate PR to handle the Azure config schema, but we need to have the same pattern for the unbranded options.
There was a problem hiding this comment.
Each client's options type is now modeled as a named local definition that inherits from the base options type using allOf. For example, SampleTypeSpecClientOptions becomes "sampleTypeSpecClientOptions": { "allOf": [{ "$ref": "#/definitions/options" }] }, and client-specific custom properties (when present) are added in a second allOf element. The client's "Options" property references this local definition via $ref. This matches the pattern from azure-sdk-for-net#57548. Fixed in 3de54bd.
There was a problem hiding this comment.
@copilot please add test cases where an options type has additional properties as compared to the base.
There was a problem hiding this comment.
@copilot we should also add a test case where an options property contains a model definition.
There was a problem hiding this comment.
Added 3 new test cases in 06c5dba:
Generate_OptionsDefinition_IncludesStringProperty— options with a string additional propertyGenerate_OptionsDefinition_IncludesIntegerProperty— options with an integer additional propertyGenerate_OptionsDefinition_IncludesMultipleMixedProperties— options with string + boolean + integer additional properties
Each test verifies the allOf pattern has 2 elements (base $ref + extension object with typed properties). All 17 tests pass.
There was a problem hiding this comment.
Added GetJsonSchemaForModel that looks up model providers in the output library and creates local definitions with their properties (referenced via $ref). New test Generate_OptionsDefinition_IncludesModelProperty creates a RetryPolicyConfig model with MaxRetries (integer) and Delay (string) properties, then verifies the schema contains a retryPolicyConfig definition with those properties and the options extension references it via $ref. Fixed in 3db3324.
There was a problem hiding this comment.
@copilot let's also add a test where the model is a constructor parameter.
There was a problem hiding this comment.
Added test Generate_ConstructorParameter_IncludesModelDefinition — creates a ConnectionConfig model (with Host string and Port integer properties) as a required constructor parameter. The test verifies that:
- The model appears as a local
definitionsentry (connectionConfig) with its properties - The model appears as a top-level client property (not under Options) with
$refto the definition
All 19 tests pass. Fixed in 577eac7.
…ions Each client's options type is now defined as a named local definition that inherits from the base 'options' type using allOf. This follows the same pattern used in the Azure emitter (azure-sdk-for-net#57548) where client options types extend the core options type. - Options without custom properties: allOf with single base ref - Options with custom properties: allOf with base ref + extension object - The client's Options property references the local definition via $ref Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/389f65d2-8aed-4cd9-a7cd-29e07b2af4f6 Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com>
…nt, mixed) Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/f557cd05-9182-46bb-806f-405ab81517b9 Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com>
… test Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/f557cd05-9182-46bb-806f-405ab81517b9 Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com>
… type definitions in schema Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/9b678996-629b-4c2f-8a16-918f2026e9d0 Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com>
|
@copilot verify that the configurationschema works using local pack of the test project |
Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/b9941a61-2c64-4fc1-b403-d6313c2ce775 Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com>
Verified the ConfigurationSchema.json works:
The regen step didn't fail because
The Regen check step didn't fail because
Already done in be700ca — |
| // Search for the model provider in the output library | ||
| var modelProvider = CodeModelGenerator.Instance.OutputLibrary.TypeProviders | ||
| .SelectMany(t => new[] { t }.Concat(t.NestedTypes)) | ||
| .FirstOrDefault(m => !(m is EnumProvider) && m.Type.Equals(modelType)); |
There was a problem hiding this comment.
should the condition check m is a ModelProvider instead of !(m is EnumProvider) ?
| if (schemaContent != null) | ||
| { | ||
| var schemaPath = Path.Combine(outputPath, "schema", "ConfigurationSchema.json"); | ||
| Directory.CreateDirectory(Path.GetDirectoryName(schemaPath)!); |
There was a problem hiding this comment.
won't CreateDirectory throw if the path argument is null?
| var extensionProperties = allOf!.AsArray()[1]?["properties"]; | ||
| var retryModeProp = extensionProperties!["RetryMode"]; | ||
| Assert.IsNotNull(retryModeProp, "Custom option property should exist"); | ||
| Assert.AreEqual("#/definitions/retryMode", retryModeProp!["$ref"]?.GetValue<string>()); |
There was a problem hiding this comment.
do you think it's worth having a few of these validate against TestData as well?
- Use 'm is ModelProvider' instead of '!(m is EnumProvider)' for more precise type checking in GetJsonSchemaForModel - Add null check for Path.GetDirectoryName result in WriteAdditionalFiles instead of using null-forgiving operator - Add TestData golden file validation for 3 representative tests: Generate_ReturnsSchema_ForClientWithSettings, Generate_ConstructorParameter_IncludesModelDefinition, Generate_HandlesMultipleClients Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
No changes needing a change description found. |
Use ReplaceLineEndings to ensure consistent LF line endings across platforms and append trailing newline to match prettier expectations. Regenerated all ConfigurationSchema.json files. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
WriteAdditionalFiles()virtual method toCodeModelGeneratorConfigurationSchemaGeneratorclass inMicrosoft.TypeSpec.Generator.ClientModelWriteAdditionalFiles()inScmCodeModelGeneratorto invoke schema generationCSharpGen.ExecuteAsync()to write additional output filescredential,options) are inherited from the System.ClientModel base schema and referenced via$ref— not duplicated locallydefinitionsfor additional non-base types (e.g., enums, models used as custom option properties) referenced via$refoptionsviaallOf(matching the Azure emitter pattern from azure-sdk-for-net#57548)Check-GitChanges.ps1to also detect new untracked files so the CI regen check catches newly generated filesdefinitions)$refto local definition)💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.