BadScript 2
Loading...
Searching...
No Matches
BadInteropApiSourceGenerator.cs
Go to the documentation of this file.
1using System.CodeDom.Compiler;
2using System.Collections.Generic;
3using System.IO;
4using System.Linq;
5using System.Text;
6
8
9using Microsoft.CodeAnalysis;
10
12
13public class BadInteropApiSourceGenerator
14{
15 private readonly SourceProductionContext m_Context;
16
17 public BadInteropApiSourceGenerator(SourceProductionContext context)
18 {
19 m_Context = context;
20 }
21
22 private string GenerateInvocation(MethodModel method)
23 {
24 StringBuilder sb = new StringBuilder();
25
26 if (method.IsVoidReturn)
27 {
28 sb.Append("{");
29 }
30 else
31 {
32 sb.Append("BadObject.Wrap(");
33 }
34
35 sb.Append($"{method.MethodName}(");
36 bool hasCtx = method.Parameters.Any(x => x.IsContext);
37 List<string> args = new List<string>();
38
39 for (int i = 0; i < method.Parameters.Length; i++)
40 {
41 ParameterModel parameter = method.Parameters[i];
42
43 if (parameter.IsContext)
44 {
45 args.Add("ctx");
46 }
47 else
48 {
49 int index = i - (hasCtx ? 1 : 0);
50 string suppressNullable = parameter.IsNullable ? "" : "!";
51
52 if (parameter.IsRestArgs)
53 {
54 if (index == 0)
55 {
56 args.Add($"new BadArray(args.ToList()).Unwrap<{parameter.CsharpType}>()");
57 }
58 else
59 {
60 args.Add($"new BadArray(args.Skip({index}).ToList()).Unwrap<{parameter.CsharpType}>()");
61 }
62 }
63 else if (parameter.HasDefaultValue)
64 {
65 args.Add($"GetParameter<{parameter.CsharpType}>(args, {index}, {parameter.DefaultValue ?? $"default({parameter.CsharpType})"}){suppressNullable}"
66 );
67 }
68 else
69 {
70 args.Add($"GetParameter<{parameter.CsharpType}>(args, {index}){suppressNullable}");
71 }
72 }
73 }
74
75 sb.Append(string.Join(", ", args));
76 sb.Append(")");
77
78 if (method.IsVoidReturn)
79 {
80 sb.Append("; return BadObject.Null; }");
81 }
82 else
83 {
84 sb.Append($", {method.AllowNativeReturn.ToString().ToLower()})");
85 }
86
87 return sb.ToString();
88 }
89
90 private string GenerateParameterSource(ParameterModel model)
91 {
92 return
93 $"new BadFunctionParameter(\"{model.Name}\", {model.HasDefaultValue.ToString().ToLower()}, {(!model.IsNullable).ToString().ToLower()}, {model.IsRestArgs.ToString().ToLower()}, null, BadNativeClassBuilder.GetNative(\"{model.Type}\"))";
94 }
95
96 private void GenerateMethodSource(IndentedTextWriter sb, MethodModel method)
97 {
98 sb.WriteLine("target.SetProperty(");
99 sb.Indent++;
100 sb.WriteLine($"\"{method.ApiMethodName}\",");
101 sb.WriteLine("new BadInteropFunction(");
102 sb.Indent++;
103 sb.WriteLine($"\"{method.ApiMethodName}\",");
104 sb.WriteLine($"(ctx, args) => {GenerateInvocation(method)},");
105 sb.WriteLine("false,");
106 sb.Write($"BadNativeClassBuilder.GetNative(\"{method.ReturnType}\")");
107
108 if (method.Parameters.Any(x => !x.IsContext))
109 {
110 sb.WriteLine(",");
111 }
112 else
113 {
114 sb.WriteLine();
115 }
116
117 for (int i = 0; i < method.Parameters.Length; i++)
118 {
119 ParameterModel parameter = method.Parameters[i];
120
121 if (parameter.IsContext)
122 {
123 continue;
124 }
125
126 sb.WriteLine(GenerateParameterSource(parameter) + (i == method.Parameters.Length - 1 ? "" : ","));
127 }
128
129 sb.Indent--;
130 sb.WriteLine(").SetMetaData(");
131 sb.Indent++;
132 sb.WriteLine("new BadMetaData(");
133 sb.Indent++;
134 sb.WriteLine($"\"{method.Description}\",");
135 sb.WriteLine($"\"{method.ReturnDescription}\",");
136 sb.WriteLine($"\"{method.ReturnType}\",");
137 sb.WriteLine("new Dictionary<string, BadParameterMetaData>");
138 sb.WriteLine("{");
139 sb.Indent++;
140
141 foreach (ParameterModel parameter in method.Parameters)
142 {
143 if (parameter.IsContext)
144 {
145 continue;
146 }
147
148 if (parameter.HasDefaultValue)
149 {
150 sb.WriteLine($"{{\"{parameter.Name}\", new BadParameterMetaData(\"{parameter.Type}\", \"{parameter.Description}\\nDefault Value: {parameter.DefaultValue!.Replace("\"", "\\\"")}\")}},"
151 );
152 }
153 else
154 {
155 sb.WriteLine($"{{\"{parameter.Name}\", new BadParameterMetaData(\"{parameter.Type}\", \"{parameter.Description}\")}},"
156 );
157 }
158 }
159
160 sb.Indent--;
161 sb.WriteLine("}");
162 sb.Indent--;
163 sb.WriteLine(")");
164 sb.Indent--;
165 sb.WriteLine(")");
166 sb.Indent--;
167 sb.WriteLine(");");
168 }
169
170 public string GenerateModelSource(SourceProductionContext context, ApiModel apiModel, bool isError)
171 {
172 IndentedTextWriter tw = new IndentedTextWriter(new StringWriter());
173 tw.WriteLine("#nullable enable");
174 tw.WriteLine("using System.Collections.Generic;");
175 tw.WriteLine("using BadScript2.Parser;");
176 tw.WriteLine("using BadScript2.Runtime.Interop.Reflection;");
177 tw.WriteLine("using BadScript2.Runtime.Objects;");
178 tw.WriteLine("using BadScript2.Runtime.Interop.Functions;");
179 tw.WriteLine("using BadScript2.Runtime.Objects.Functions;");
180 tw.WriteLine("using BadScript2.Runtime.Objects.Types;");
181 tw.WriteLine("using BadScript2.Runtime.Interop;");
182 tw.WriteLine();
183 tw.WriteLine($"namespace {apiModel.Namespace};");
184 tw.WriteLine($"partial class {apiModel.ClassName} : BadScript2.Interop.BadAutoGeneratedInteropApi");
185 tw.WriteLine("{");
186 tw.Indent++;
187
188 tw.WriteLine($"{(apiModel.ConstructorPrivate ? "private" : "public")} {apiModel.ClassName}() : base(\"{apiModel.ApiName}\") {{ }}"
189 );
190 tw.WriteLine();
191 tw.WriteLine("protected override void LoadApi(BadTable target)");
192 tw.WriteLine("{");
193 tw.Indent++;
194 tw.WriteLine("AdditionalData(target);");
195
196 if (!isError && apiModel.Methods.Length != 0)
197 {
198 tw.WriteLine("T? GetParameter<T>(BadObject[] args, int i, T? defaultValue = default(T)) => args.Length>i?args[i].Unwrap<T>():defaultValue;"
199 );
200
201 foreach (MethodModel method in apiModel.Methods)
202 {
203 GenerateMethodSource(tw, method);
204 }
205 }
206
207 tw.Indent--;
208 tw.WriteLine("}");
209 tw.Indent--;
210 tw.WriteLine("}");
211
212 tw.Flush();
213
214 string str = tw.InnerWriter.ToString();
215
216 return str;
217 }
218}