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