microsoft/TypeAgent

Public

mirrored fromhttps://github.com/microsoft/TypeAgentAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
d4944c6517c9a96a3c419f827769f518913f1b75

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

dotnet/autoShell.Generators/SchemaParser.cs

255lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4using System.Collections.Generic;
5using System.Text.Json;
6
7namespace autoShell.Generators;
8
9/// <summary>
10/// Represents a parsed action definition from a .pas.json schema file.
11/// </summary>
12internal class ActionDefinition
13{
14 public string ActionName { get; set; }
15 public string TypeName { get; set; }
16 public List<ParameterDefinition> Parameters { get; set; } = [];
17}
18
19/// <summary>
20/// Represents a single parameter field within an action definition.
21/// </summary>
22internal class ParameterDefinition
23{
24 public string JsonName { get; set; }
25 public string CSharpName { get; set; }
26 public string CSharpType { get; set; }
27 public bool IsOptional { get; set; }
28 public string DefaultValue { get; set; }
29}
30
31/// <summary>
32/// Parses .pas.json schema files to extract action definitions with their parameter types.
33/// </summary>
34internal static class SchemaParser
35{
36 /// <summary>
37 /// Parses a .pas.json file and returns all action definitions found.
38 /// </summary>
39 public static List<ActionDefinition> Parse(string json)
40 {
41 var actions = new List<ActionDefinition>();
42
43 using var doc = JsonDocument.Parse(json);
44 var root = doc.RootElement;
45
46 if (!root.TryGetProperty("types", out var types))
47 {
48 return actions;
49 }
50
51 foreach (var typeProp in types.EnumerateObject())
52 {
53 var actionDef = TryParseActionType(typeProp);
54 if (actionDef != null)
55 {
56 actions.Add(actionDef);
57 }
58 }
59
60 return actions;
61 }
62
63 private static ActionDefinition TryParseActionType(JsonProperty typeProp)
64 {
65 var typeObj = typeProp.Value;
66
67 // Navigate: type.fields.actionName.type.typeEnum[0]
68 if (!typeObj.TryGetProperty("type", out var typeInfo))
69 {
70 return null;
71 }
72
73 if (!typeInfo.TryGetProperty("fields", out var fields))
74 {
75 return null;
76 }
77
78 if (!fields.TryGetProperty("actionName", out var actionNameField))
79 {
80 return null;
81 }
82
83 if (!actionNameField.TryGetProperty("type", out var actionNameType))
84 {
85 return null;
86 }
87
88 if (!actionNameType.TryGetProperty("typeEnum", out var typeEnum))
89 {
90 return null;
91 }
92
93 if (typeEnum.GetArrayLength() == 0)
94 {
95 return null;
96 }
97
98 string actionName = typeEnum[0].GetString();
99 if (string.IsNullOrEmpty(actionName))
100 {
101 return null;
102 }
103
104 var def = new ActionDefinition
105 {
106 ActionName = actionName,
107 TypeName = ToPascalCase(actionName) + "Params"
108 };
109
110 // Navigate: type.fields.parameters.type.fields
111 if (fields.TryGetProperty("parameters", out var parametersField) &&
112 parametersField.TryGetProperty("type", out var parametersType) &&
113 parametersType.TryGetProperty("fields", out var paramFields))
114 {
115 foreach (var paramProp in paramFields.EnumerateObject())
116 {
117 var paramDef = ParseParameter(paramProp);
118 if (paramDef != null)
119 {
120 def.Parameters.Add(paramDef);
121 }
122 }
123 }
124
125 return def;
126 }
127
128 private static ParameterDefinition ParseParameter(JsonProperty paramProp)
129 {
130 string jsonName = paramProp.Name;
131 var paramType = paramProp.Value;
132
133 if (!paramType.TryGetProperty("type", out var typeInfo))
134 {
135 return null;
136 }
137
138 bool isOptional = false;
139 if (paramType.TryGetProperty("optional", out var optionalProp))
140 {
141 isOptional = optionalProp.GetBoolean();
142 }
143
144 string csharpType = ResolveCSharpType(typeInfo, out bool isNullable);
145 isOptional = isOptional || isNullable;
146
147 string defaultValue = GetDefaultValue(csharpType, isOptional);
148
149 return new ParameterDefinition
150 {
151 JsonName = jsonName,
152 CSharpName = ToPascalCase(jsonName),
153 CSharpType = isOptional && IsValueType(csharpType) ? csharpType + "?" : csharpType,
154 IsOptional = isOptional,
155 DefaultValue = defaultValue
156 };
157 }
158
159 private static string ResolveCSharpType(JsonElement typeInfo, out bool isNullable)
160 {
161 isNullable = false;
162
163 // Simple type: { "type": "number" }
164 if (typeInfo.TryGetProperty("type", out var simpleType))
165 {
166 string typeStr = simpleType.GetString();
167 return typeStr switch
168 {
169 "number" => "int",
170 "boolean" => "bool",
171 "string" => "string",
172 "string-union" => "string",
173 "type-union" => ResolveTypeUnion(typeInfo, out isNullable),
174 "array" => ResolveArrayType(typeInfo),
175 "type-reference" => "string",
176 "object" => "string",
177 _ => "string",
178 };
179 }
180
181 return "string";
182 }
183
184 private static string ResolveArrayType(JsonElement typeInfo)
185 {
186 if (typeInfo.TryGetProperty("elementType", out var elementType))
187 {
188 string elementCSharpType = ResolveCSharpType(elementType, out _);
189 return elementCSharpType + "[]";
190 }
191
192 return "string[]";
193 }
194
195 private static string ResolveTypeUnion(JsonElement typeInfo, out bool isNullable)
196 {
197 isNullable = false;
198
199 if (!typeInfo.TryGetProperty("types", out var unionTypes))
200 {
201 return "string";
202 }
203
204 string resolvedType = "string";
205 foreach (var unionMember in unionTypes.EnumerateArray())
206 {
207 if (unionMember.TryGetProperty("type", out var memberType))
208 {
209 string memberTypeStr = memberType.GetString();
210 if (memberTypeStr == "undefined" || memberTypeStr == "null")
211 {
212 isNullable = true;
213 }
214 else
215 {
216 resolvedType = ResolveCSharpType(unionMember, out _);
217 }
218 }
219 }
220
221 return resolvedType;
222 }
223
224 private static bool IsValueType(string csharpType)
225 {
226 return csharpType == "int" || csharpType == "bool" || csharpType == "double";
227 }
228
229 private static string GetDefaultValue(string csharpType, bool isOptional)
230 {
231 if (isOptional)
232 {
233 return "null";
234 }
235
236 if (csharpType.EndsWith("[]"))
237 {
238 return "null";
239 }
240
241 return csharpType switch
242 {
243 "int" => "0",
244 "bool" => "false",
245 "double" => "0.0",
246 "string" => "\"\"",
247 _ => "\"\"",
248 };
249 }
250
251 private static string ToPascalCase(string name)
252 {
253 return string.IsNullOrEmpty(name) ? name : char.ToUpperInvariant(name[0]) + name.Substring(1);
254 }
255}