public void Test() { GeneratedCodeForLang ret = GenerateCodes(); Console.WriteLine(ret.TypeScript.ToString()); return; var model = cs_types.Model; var type_classes = cs_types.Root.DescendantNodes() .OfType <ClassDeclarationSyntax>(); foreach (ClassDeclarationSyntax v in type_classes) { WriteLine(v.Identifier.Text); var info = model.GetDeclaredSymbol(v); var x = info.GetMembers(); foreach (var y in x) { WriteLine(y.Name); } break; } Console.WriteLine(); }
void generate_tests(GeneratedCodeForLang ret) { var test_class = cs_tests.Root.DescendantNodes().OfType <ClassDeclarationSyntax>().Where(c => c.Identifier.Text == "VPNRPCTest").First(); CcWalker w = new CcWalker(cs_tests, TargetLang.TypeScript); //CcWalker w = new CcWalker(cs_tests, TargetLang.CSharp); w.Visit(test_class); WriteLine(w.ToString()); }
public GeneratedCodeForLang GenerateCodes() { GeneratedCodeForLang ret = new GeneratedCodeForLang(); generate_types(ret); generate_stubs(ret); generate_tests(ret); return(ret); }
void generate_stubs(GeneratedCodeForLang ret) { var model = cs_stubs.Model; var rpc_class = cs_stubs.Root.DescendantNodes().OfType <ClassDeclarationSyntax>().Where(c => c.Identifier.Text == "VpnServerRpc").First(); var members = model.GetDeclaredSymbol(rpc_class).GetMembers(); var methods = members.Where(m => m is IMethodSymbol).Select(m => m as IMethodSymbol).Where(m => m.IsStatic == false) .Where(m => m.IsAsync).Where(m => m.Name != "CallAsync"); foreach (var method in methods) { string method_name = method.Name; if (method_name.EndsWith("Async") == false) { throw new ApplicationException($"{method.Name}: method_name = {method_name}"); } method_name = method_name.Substring(0, method_name.Length - 5); INamedTypeSymbol ret_type = (INamedTypeSymbol)method.ReturnType; if (ret_type.Name != "Task") { throw new ApplicationException($"{method.Name}: ret_type.Name = {ret_type.Name}"); } var ret_type_args = ret_type.TypeArguments; if (ret_type_args.Length != 1) { throw new ApplicationException($"{method.Name}: type_args.Length = {ret_type_args.Length}"); } var ret_type_name = ret_type_args[0].Name; if (method.Parameters.Length >= 2) { throw new ApplicationException($"{method.Name}: method.Parameters.Length = {method.Parameters.Length}"); } if (method.DeclaringSyntaxReferences.Length != 1) { throw new ApplicationException($"{method.Name}: method.DeclaringSyntaxReferences.Length = {method.DeclaringSyntaxReferences.Length}"); } MethodDeclarationSyntax syntax = (MethodDeclarationSyntax)method.DeclaringSyntaxReferences[0].GetSyntax(); if (syntax.Body != null) { throw new ApplicationException($"{method.Name}: syntax.Body != null"); } if (syntax.ExpressionBody == null) { throw new ApplicationException($"{method.Name}: syntax.ExpressionBody == null"); } ArrowExpressionClauseSyntax body = syntax.ExpressionBody; InvocationExpressionSyntax invoke = body.DescendantNodes().OfType <InvocationExpressionSyntax>().Single(); if (model.GetSymbolInfo(invoke.Expression).Symbol.Name != "CallAsync") { throw new ApplicationException($"{method.Name}: model.GetSymbolInfo(invoke.Expression).Symbol.Name = {model.GetSymbolInfo(invoke.Expression).Symbol.Name}"); } if (invoke.ArgumentList.Arguments.Count != 2) { throw new ApplicationException($"{method.Name}: invoke.ArgumentList.Arguments.Count = {invoke.ArgumentList.Arguments.Count}"); } LiteralExpressionSyntax str_syntax = (LiteralExpressionSyntax)invoke.ArgumentList.Arguments[0].Expression; string str = str_syntax.Token.Text; StringWriter ts = new StringWriter(); string doc2 = method.GetDocumentStr(); if (string.IsNullOrEmpty(doc2) == false) { ts.WriteLine($" /** {doc2} */"); } if (method.Parameters.Length == 0) { ts.WriteLine($" public {method_name} = (): Promise<{ret_type_name}> =>"); ts.WriteLine(" {"); ts.WriteLine($" return this.CallAsync<{ret_type_name}>({str}, new {ret_type_name}());"); ts.WriteLine(" }"); ts.WriteLine(" "); } else { ts.WriteLine($" public {method_name} = (in_param: {ret_type_name}): Promise<{ret_type_name}> =>"); ts.WriteLine(" {"); ts.WriteLine($" return this.CallAsync<{ret_type_name}>({str}, in_param);"); ts.WriteLine(" }"); ts.WriteLine(" "); } ret.TypeScript.Stubs.AddPart(method.DeclaringSyntaxReferences[0].Span.Start, ts.ToString()); } }
void generate_types(GeneratedCodeForLang ret) { var model = cs_types.Model; var class_list = cs_types.Root.DescendantNodes().OfType <ClassDeclarationSyntax>(); foreach (ClassDeclarationSyntax c in class_list) { StringWriter ts = new StringWriter(); string doc = model.GetDeclaredSymbol(c).GetDocumentStr(); if (string.IsNullOrEmpty(doc) == false) { ts.WriteLine($"/** {doc} */"); } ts.WriteLine($"export class {c.Identifier.Text}"); ts.WriteLine("{"); foreach (var member in model.GetDeclaredSymbol(c).GetMembers()) { string json_name = ""; bool json_name_has_special_char = false; var atts = member.GetAttributes(); var y = atts.Where(x => x.AttributeClass.Name == "JsonPropertyAttribute").FirstOrDefault(); if (y != null) { json_name = y.ConstructorArguments.FirstOrDefault().Value.ToString(); if (json_name.IndexOf(':') != -1 || json_name.IndexOf('.') != -1) { json_name_has_special_char = true; } } string default_value = "\"\""; switch (member) { case IFieldSymbol field: string ts_type = ""; ITypeSymbol type = field.Type; switch (type.Kind) { case SymbolKind.NamedType: switch (type.Name) { case "UInt32": case "UInt64": ts_type = "number"; default_value = "0"; break; case "String": ts_type = "string"; break; case "Boolean": ts_type = "boolean"; default_value = "false"; break; case "DateTime": ts_type = "Date"; default_value = "new Date()"; break; default: if (type.TypeKind == TypeKind.Enum) { ts_type = type.Name; default_value = "0"; break; } throw new ApplicationException($"{c.Identifier}.{member.Name}: type.Name = {type.Name}"); } break; case SymbolKind.ArrayType: ITypeSymbol type2 = ((IArrayTypeSymbol)type).ElementType; default_value = "[]"; switch (type2.Kind) { case SymbolKind.NamedType: switch (type2.Name) { case "UInt32": case "UInt64": ts_type = "number[]"; break; case "String": ts_type = "string[]"; break; case "Boolean": ts_type = "boolean[]"; break; case "Byte": ts_type = "Uint8Array"; default_value = "new Uint8Array([])"; break; default: if (type2.ContainingAssembly.Name == csc.AssemblyName) { ts_type = type2.Name + "[]"; break; } throw new ApplicationException($"{c.Identifier}.{member.Name}: type2.Name = {type2.Name}"); } break; default: throw new ApplicationException($"{c.Identifier}.{member.Name}: type2.Kind = {type2.Kind}"); } break; default: throw new ApplicationException($"{c.Identifier}.{member.Name}: type.Kind = {type.Kind}"); } if (string.IsNullOrEmpty(ts_type) == false) { string field_name = field.Name; if (string.IsNullOrEmpty(json_name) == false) { field_name = json_name; } if (json_name_has_special_char) { field_name = $"[\"{json_name}\"]"; } string doc2 = member.GetDocumentStr(); if (string.IsNullOrEmpty(doc2) == false) { ts.WriteLine($" /** {doc2} */"); } ts.WriteLine($" public {field_name}: {ts_type} = {default_value};"); ts.WriteLine(); } break; case IMethodSymbol method when method.MethodKind == MethodKind.Constructor: break; default: throw new ApplicationException($"{c.Identifier}.{member.Name}: type = {member.GetType()}"); } } if (string.IsNullOrEmpty(doc) == false) { ts.WriteLine($" /** Constructor for the '{c.Identifier.Text}' class: {doc} */"); } ts.WriteLine($" public constructor(init?: Partial<{c.Identifier.Text}>)"); ts.WriteLine(" {"); ts.WriteLine(" Object.assign(this, init);"); ts.WriteLine(" }"); ts.WriteLine("}"); ts.WriteLine(); ret.TypeScript.Types.AddPart(c.SpanStart, ts.ToString()); } var enum_list = cs_types.Root.DescendantNodes().OfType <EnumDeclarationSyntax>(); foreach (EnumDeclarationSyntax e in enum_list) { StringWriter ts = new StringWriter(); string doc = model.GetDeclaredSymbol(e).GetDocumentStr(); if (string.IsNullOrEmpty(doc) == false) { ts.WriteLine($"/** {doc} */"); } ts.WriteLine($"export enum {e.Identifier.Text}"); ts.WriteLine("{"); foreach (var member in model.GetDeclaredSymbol(e).GetMembers()) { switch (member) { case IFieldSymbol field: if (field.IsConst && field.IsDefinition) { string doc2 = member.GetDocumentStr(); if (string.IsNullOrEmpty(doc2) == false) { ts.WriteLine($" /** {doc2} */"); } ts.WriteLine($" {field.Name} = {field.ConstantValue},"); ts.WriteLine(); } break; } } ts.WriteLine("}"); ts.WriteLine(); ret.TypeScript.Types.AddPart(e.SpanStart, ts.ToString()); } }
void generate_types(GeneratedCodeForLang ret) { var model = cs_types.Model; var class_list = cs_types.Root.DescendantNodes().OfType <ClassDeclarationSyntax>(); foreach (ClassDeclarationSyntax c in class_list) { StringWriter ts = new StringWriter(); ts.WriteLine($"export class {c.Identifier.Text}"); ts.WriteLine("{"); foreach (var member in model.GetDeclaredSymbol(c).GetMembers()) { switch (member) { case IFieldSymbol field: string ts_type = ""; ITypeSymbol type = field.Type; switch (type.Kind) { case SymbolKind.NamedType: switch (type.Name) { case "UInt32": case "UInt64": ts_type = "number"; break; case "String": ts_type = "string"; break; case "Boolean": ts_type = "boolean"; break; case "DateTime": ts_type = "Date"; break; default: if (type.TypeKind == TypeKind.Enum) { ts_type = type.Name; break; } throw new ApplicationException($"{c.Identifier}.{member.Name}: type.Name = {type.Name}"); } break; case SymbolKind.ArrayType: ITypeSymbol type2 = ((IArrayTypeSymbol)type).ElementType; switch (type2.Kind) { case SymbolKind.NamedType: switch (type2.Name) { case "UInt32": case "UInt64": ts_type = "number[]"; break; case "String": ts_type = "string[]"; break; case "Boolean": ts_type = "boolean[]"; break; case "Byte": ts_type = "Uint8Array"; break; default: if (type2.ContainingAssembly.Name == csc.AssemblyName) { ts_type = type2.Name + "[]"; break; } throw new ApplicationException($"{c.Identifier}.{member.Name}: type2.Name = {type2.Name}"); } break; default: throw new ApplicationException($"{c.Identifier}.{member.Name}: type2.Kind = {type2.Kind}"); } break; default: throw new ApplicationException($"{c.Identifier}.{member.Name}: type.Kind = {type.Kind}"); } if (string.IsNullOrEmpty(ts_type) == false) { ts.WriteLine($" {field.Name}?: {ts_type};"); } break; case IMethodSymbol method when method.MethodKind == MethodKind.Constructor: break; default: throw new ApplicationException($"{c.Identifier}.{member.Name}: type = {member.GetType()}"); } } ts.WriteLine("}"); ts.WriteLine(); ret.TypeScript.Types.AddPart(c.SpanStart, ts.ToString()); } var enum_list = cs_types.Root.DescendantNodes().OfType <EnumDeclarationSyntax>(); foreach (EnumDeclarationSyntax e in enum_list) { StringWriter ts = new StringWriter(); ts.WriteLine($"export enum {e.Identifier.Text}"); ts.WriteLine("{"); foreach (var member in model.GetDeclaredSymbol(e).GetMembers()) { switch (member) { case IFieldSymbol field: if (field.IsConst && field.IsDefinition) { ts.WriteLine($" {field.Name} = {field.ConstantValue},"); } break; } } ts.WriteLine("}"); ts.WriteLine(); ret.TypeScript.Types.AddPart(e.SpanStart, ts.ToString()); } }