Skip to content

Commit

Permalink
Merge pull request #215 from mhutch/aspire-schemas
Browse files Browse the repository at this point in the history
Add .NET Aspire schemas
  • Loading branch information
mhutch authored Apr 26, 2024
2 parents 8e341fd + 577c095 commit a0d20ca
Show file tree
Hide file tree
Showing 12 changed files with 139 additions and 17 deletions.
2 changes: 2 additions & 0 deletions MonoDevelop.MSBuild/Language/Typesystem/CustomTypeInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public CustomTypeInfo (
}
}

public bool IsAnonymous => Name is null || Name.Length == 0 || Name[0] == '#';

public string? Name { get; }
public DisplayText Description { get; }
public bool AllowUnknownValues { get; }
Expand Down
4 changes: 4 additions & 0 deletions MonoDevelop.MSBuild/Schema/BuiltInSchema.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ static MSBuildSchema Load (BuiltInSchemaId[] schemaIds, out IList<MSBuildSchemaL
static readonly Dictionary<(string? sdkId, string filename), BuiltInSchemaId[]> filenameToIdMap = new (BuiltInSchemaId[] resourceId, string? sdkId, string filename)[] {
([ BuiltInSchemaId.Android ], null, "Xamarin.Android.Common.targets"),
([ BuiltInSchemaId.Appx ], null, "Microsoft.DesktopBridge.targets"),
([ BuiltInSchemaId.AspireAppHost ], null, "Aspire.Hosting.AppHost.targets" ),
([ BuiltInSchemaId.AspireHostingOrchestration ], "Aspire.Hosting.Orchestration", sdkTargets ),
([ BuiltInSchemaId.AspireHostingSdk ], "Aspire.Hosting.Sdk", sdkTargets ),
([ BuiltInSchemaId.AspireDashboardSdk ], "Aspire.Dashboard.Sdk", sdkTargets ),
([ BuiltInSchemaId.AspNetCore ], "Microsoft.NET.Sdk.Web", sdkTargets),
([ BuiltInSchemaId.CodeAnalysis ], null, "Microsoft.CodeAnalysis.targets"),
([ BuiltInSchemaId.CommonTargets ], null, "Microsoft.Common.targets"),
Expand Down
6 changes: 5 additions & 1 deletion MonoDevelop.MSBuild/Schema/BuiltInSchemaId.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,9 @@ enum BuiltInSchemaId
ProjectSystemMps,
ProjectSystemCps,
GenerateAssemblyInfo,
ValidatePackage
ValidatePackage,
AspireAppHost,
AspireHostingOrchestration,
AspireHostingSdk,
AspireDashboardSdk
}
2 changes: 1 addition & 1 deletion MonoDevelop.MSBuild/Schema/DescriptionFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ static string FormatKind (MSBuildValueKind kind, CustomTypeInfo customTypeInfo)
case MSBuildValueKind.NuGetVersion:
return "nuget-version";
case MSBuildValueKind.CustomType:
if (customTypeInfo != null && customTypeInfo.Name != null) {
if (customTypeInfo != null && !customTypeInfo.IsAnonymous) {
return customTypeInfo.Name;
}
// derived types inherit the name from the base type
Expand Down
18 changes: 10 additions & 8 deletions MonoDevelop.MSBuild/Schema/MSBuildSchema.SchemaLoadState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -428,15 +428,15 @@ bool GetValueString ([NotNullWhen (true)] out string? value)
}

if (token is JArray conciseDef) {
return (MSBuildValueKind.CustomType, ReadConciseCustomTypeDefinition (conciseDef));
return (MSBuildValueKind.CustomType, ReadConciseCustomTypeDefinition (conciseDef, null));
}

if (token is not JObject typeDefObj) {
AddError (token, "Type must be an intrinsic type string, type definition array, type definition object, or type reference object");
return (MSBuildValueKind.Unknown, null);
}

(var definition, var reference) = ReadCustomTypeDefinitionOrReference (typeDefObj);
(var definition, var reference) = ReadCustomTypeDefinitionOrReference (typeDefObj, null);

if (reference != null) {
if (CustomTypes is not null && CustomTypes.TryGetValue (reference, out var resolved)) {
Expand All @@ -456,7 +456,7 @@ bool GetValueString ([NotNullWhen (true)] out string? value)
CustomTypeInfo? ReadCustomTypeDefinition (JObject customTypeContainer, string? customTypeId, JToken? customTypeDef)
{
if (customTypeDef is JArray conciseDef) {
return ReadConciseCustomTypeDefinition (conciseDef);
return ReadConciseCustomTypeDefinition (conciseDef, customTypeId);
}
if (customTypeDef is not JObject customTypeDefObj) {
AddError (customTypeDef ?? customTypeContainer, customTypeId is not null
Expand All @@ -465,7 +465,7 @@ bool GetValueString ([NotNullWhen (true)] out string? value)
return null;
}

(var definition, var reference) = ReadCustomTypeDefinitionOrReference (customTypeDefObj);
(var definition, var reference) = ReadCustomTypeDefinitionOrReference (customTypeDefObj, customTypeId);
if (reference != null) {
AddWarning (customTypeDefObj, customTypeId is not null
? $"Custom type definition '{customTypeId}' cannot be a type reference"
Expand All @@ -476,7 +476,9 @@ bool GetValueString ([NotNullWhen (true)] out string? value)
return definition;
}

CustomTypeInfo ReadConciseCustomTypeDefinition (JArray conciseCustomTypeDef)
static string? MakeAnonymousTypeName (string? customTypeId) => customTypeId is null? null : $"#{customTypeId}";

CustomTypeInfo ReadConciseCustomTypeDefinition (JArray conciseCustomTypeDef, string? customTypeId)
{
var values = new List<CustomTypeValue> (conciseCustomTypeDef.Count);
foreach (var defVal in conciseCustomTypeDef) {
Expand All @@ -486,10 +488,10 @@ CustomTypeInfo ReadConciseCustomTypeDefinition (JArray conciseCustomTypeDef)
}
values.Add (new CustomTypeValue (customTypeValue, null));
}
return new (values);
return new (values, MakeAnonymousTypeName (customTypeId));
}

(CustomTypeInfo? definition, string? reference) ReadCustomTypeDefinitionOrReference (JObject customTypeObj)
(CustomTypeInfo? definition, string? reference) ReadCustomTypeDefinitionOrReference (JObject customTypeObj, string? customTypeId)
{
var enumerator = customTypeObj.GetEnumerator ();
if (!enumerator.MoveNext ()) {
Expand Down Expand Up @@ -609,7 +611,7 @@ bool GetValueBool ([NotNullWhen (true)] out bool? value)
allowUnknownValues = true;
}

return (new CustomTypeInfo (values, name, description, allowUnknownValues ?? false, baseValueKind ?? MSBuildValueKind.Unknown, caseSensitive ?? false, analyzerHints, helpUrl), null);
return (new CustomTypeInfo (values, name ?? MakeAnonymousTypeName (customTypeId), description, allowUnknownValues ?? false, baseValueKind ?? MSBuildValueKind.Unknown, caseSensitive ?? false, analyzerHints, helpUrl), null);
}

CustomTypeValue ReadCustomTypeValue (JObject customTypeValueCollection, string customTypeValueName, JToken? customTypeValueToken)
Expand Down
5 changes: 3 additions & 2 deletions MonoDevelop.MSBuild/Schema/MSBuildSchema.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,10 @@ void LoadInternal (TextReader reader, out IList<MSBuildSchemaLoadError> loadErro
// all custom types are resolvable
state.LoadCustomTypes (customTypes);

// only named custom types are surfaced directly on the schema
// only named custom types are surfaced directly on the schema,
// as well as anonymous types deriving from `warning-code` as those are needed for completion
foreach (var ct in state.CustomTypes.Values) {
if (!string.IsNullOrEmpty (ct.Name)) {
if (ct.Name is not null && (!ct.IsAnonymous || ct.BaseKind == MSBuildValueKind.WarningCode)) {
Types.Add (ct.Name, ct);
}
}
Expand Down
5 changes: 0 additions & 5 deletions MonoDevelop.MSBuild/Schemas/AspNetCore.buildschema.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@
"AspNetCoreModuleV2"
]
},
"UserSecretsId": {
"description": "The ID that will be used to locate the file storing secret configuration values for this project at development time. Although by default this is a GUID value, arbitrary strings may be used.",
"type": "string",
"helpUrl": "https://learn.microsoft.com/aspnet/core/security/app-secrets?view=aspnetcore-8.0&tabs=windows#enable-secret-storage"
},
"BlazorEnableTimeZoneSupport": {
"description": "Indicates whether Blazor WebAssembly should include a data file to make timezone information correct. Setting this to `false` will reduce your app size.",
"defaultValue": "true",
Expand Down
40 changes: 40 additions & 0 deletions MonoDevelop.MSBuild/Schemas/AspireAppHost.buildschema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"license": "Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.",
"properties": {
"AspireGeneratedClassesVisibility": {
"description": "Controls the visibility of generated .NET Aspire classes, as a C# keyword",
"type": {
"values": {
"public": "The generated class will have `public` visibility",
"internal": "The generated class will have `internal` visibility"
}
},
"defaultValue": "public"
},
"SkipValidateAspireHostProjectResources": {
"description": "Skip validation of .NET Aspire AppHost project references",
"type": "bool",
"defaultValue": "false"
},
"AspirePublisher": {
"description": "Sets the publisher to be invoked by the `GenerateAspireManifest` target",
"type": "string",
"defaultValue": "manifest"
},
"AspireManifestPublishOutputPath": {
"description": "The path to the output directory for the .NET Aspire manifest publish",
"type": "folder-with-slash"
}
},
"targets": {
"GenerateAspireManifest": "Generates a .NET Aspire manifest file for the project at the path indicated by the `AspireManifestPublishOutputPath` property "
},
"types": {
"aspire-apphost-warning": {
"baseType": "warning-code",
"values": {
"ASPIRE004": "Project referenced by Aspire AppHost is not an executable"
}
}
},
}
13 changes: 13 additions & 0 deletions MonoDevelop.MSBuild/Schemas/AspireDashboardSdk.buildschema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"license": "Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.",
"properties": {
"AspireDashboardDir": {
"description": "The directory where the .NET Aspire Dashboard is located",
"type": "folder-with-slash"
},
"AspireDashboardPath": {
"description": "The path to the .NET Aspire Dashboard binary",
"type": "file"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"license": "Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.",
"properties": {
"DcpDir": {
"description": "The path to the directory containing the DCP tools.",
"type": "folder-with-slash"
},
"DcpExtensionsDir": {
"description": "The path to the directory containing the DCP tool extensions.",
"type": "folder-with-slash"
},
"DcpBinDir": {
"description": "The path to the directory containing the DCP tool extension binaries.",
"type": "folder-with-slash"
},
"DcpCliPath": {
"description": "The path to the DCP CLI executable.",
"type": "file"
}
}
}
22 changes: 22 additions & 0 deletions MonoDevelop.MSBuild/Schemas/AspireHostingSdk.buildschema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"license": "Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.",
"types": {
"aspire-hosting-sdk-warning": {
"baseType": "warning-code",
"values": {
"ASPIRE002": "Aspire AppHost project has missing dependencies",
"ASPIRE003": "Visual Studio version is too old for Aspire AppHost project"
}
}
},
"metadata": [
{
"$appliesTo": [ "ProjectReference" ],
"IsAspireProjectResource":{
"type": "bool",
"description": "Indicates that the referenced project should be orchestrated by the .NET Aspire AppHost, instead of referencing its output assembly.",
"defaultValue": "true"
}
}
]
}
18 changes: 18 additions & 0 deletions MonoDevelop.MSBuild/Schemas/NetSdk.buildschema.json
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,24 @@
"type": "version",
"helpUrl": "https://learn.microsoft.com/dotnet/core/versions/selection#self-contained-deployments-include-the-selected-runtime"
},
"IsAspireSharedProject": {
"description": "Indicates that the project is an .NET Aspire shared project, causing Visual Studio to treat it as such.",
"type": "bool"
},
"IsAspireHost": {
"description": "Indicates that the project is an .NET Aspire Host project, causing the Aspire workload targets to be referenced.",
"type": "bool"
},
"SkipAspireWorkloadManifest": {
"description": "Indicates that the project should not reference the .NET Aspire workload targets despite setting `IsAspireHost` to `true`.",
"type": "bool"
},
// this is used to generate an attribute in in Microsoft.NET.Sdk.FrameworkReferenceResolution.targets
"UserSecretsId": {
"description": "The ID that will be used to locate the file storing secret configuration values for this project at development time. Although by default this is a GUID value, arbitrary strings may be used.",
"type": "string",
"helpUrl": "https://learn.microsoft.com/aspnet/core/security/app-secrets?view=aspnetcore-8.0&tabs=windows#enable-secret-storage"
}
},

"items": {
Expand Down

0 comments on commit a0d20ca

Please sign in to comment.