public static PropertyDeclarationSyntax CreatePropertyDeclaration(string typeName, string name, string description, bool optional = false, bool nullable = false, bool addPostfix = false) { nullable = optional || nullable; var attributes = new List <AttributeSyntax> { Attribute(IdentifierName($"JsonPropertyName(\"{name}\")")) }; //todo: problem with nullable properties in netcoreapp3.1 see test TypeWithNullableProperties //if (nullable) attributes.Add(Attribute(IdentifierName("JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)"))); AccessorListSyntax accessorListSyntax = AccessorList( List(new[] { AccessorDeclaration( SyntaxKind.GetAccessorDeclaration) .WithSemicolonToken( Token(SyntaxKind.SemicolonToken)), AccessorDeclaration( SyntaxKind.SetAccessorDeclaration) .WithSemicolonToken( Token(SyntaxKind.SemicolonToken)) })); return(PropertyDeclaration(IdentifierName($"{typeName}{(optional ? "?" : null)}"), NamingConventions.Normalize($"{name}{(addPostfix ? "Accessor" : null)}")) .AddAttributeLists(AttributeList(SeparatedList(attributes)) .WithLeadingTrivia(CommentsHelpers.BuildCommentTrivia(description))) .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) .WithAccessorList(accessorListSyntax)); }
public static void CreateUnit(string unitName, Func <string, NamespaceDeclarationSyntax> nsFactory, string filePathFactory, params string[] usings) { unitName = NamingConventions.Normalize(unitName); CompilationUnitSyntax cu = SyntaxFactory.CompilationUnit(); cu = cu.AddUsings(usings.OrderBy(s => s) .Select(u => SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(u))) .ToArray()); var cw = new AdhocWorkspace(); cw.Options.WithChangedOption(CSharpFormattingOptions.IndentBlock, true); SyntaxNode formattedNode = Formatter.Format(cu.AddMembers(nsFactory(unitName)), cw, cw.Options); var file = new FileInfo(filePathFactory); DirectoryInfo dir = file.Directory; if (!dir !.Exists) { dir.Create(); } using FileStream fileStream = file.Exists ? file.Open(FileMode.Truncate) : file.Create(); using var sw = new StreamWriter(fileStream); formattedNode.WriteTo(sw); }
public static string GetMethodReturnType(this Result result) { if (result.GenericName != ResultGenericName.ClientResult) { throw new ArgumentOutOfRangeException(nameof(result.GenericName), result.GenericName, "Unsupported method result generic name"); } if (result.Type != ParamType.Generic) { throw new ArgumentOutOfRangeException(nameof(Result.Type), result.Type, "Unsupported method result type"); } if (result.GenericArgs.Length != 1) { throw new ArgumentException("Result should contains only one generic argument"); } GenericArg genericArg = result.GenericArgs[0]; switch (genericArg.Type) { case GenericArgType.None: return(null); case GenericArgType.Ref: return(NamingConventions.Normalize(genericArg.RefName)); default: throw new ArgumentOutOfRangeException(nameof(Type), genericArg.Type, "Unsupported generic type"); } }
public static NamespaceDeclarationSyntax CreateTonClientClass(string unitName, TonApi tonApi) { var propertyDeclarationSyntaxes = GetProperties(tonApi); var moduleNames = tonApi.Modules.Select(m => m.Name).ToArray(); VariableDeclarationSyntax variableDeclaration = VariableDeclaration(ParseTypeName("ServiceProvider")) .AddVariables(VariableDeclarator("_serviceProvider")); FieldDeclarationSyntax fieldDeclaration = FieldDeclaration(variableDeclaration) .AddModifiers(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ReadOnlyKeyword)); var statementSyntax = new[] { ParseStatement("_serviceProvider = TonClientServiceProviderBuilder.BuildTonClientServiceProvider(serviceProvider);") } .Union(moduleNames .Select(m => ParseStatement( $"{NamingConventions.Normalize(m)} = _serviceProvider.GetRequiredService<{NamingConventions.ToInterfaceName(m)}Module>();"))) .ToArray(); MethodDeclarationSyntax disposeMethod = MethodDeclaration(ParseTypeName("void"), "Dispose") .AddModifiers(Token(SyntaxKind.PublicKeyword)) .AddBodyStatements(ParseStatement("_serviceProvider?.Dispose();")); ConstructorDeclarationSyntax constructorDeclaration = ConstructorDeclaration(unitName) .AddParameterListParameters(Parameter(Identifier("serviceProvider = null")).WithType(IdentifierName("IServiceProvider"))) .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) .WithBody(Block(statementSyntax)); ClassDeclarationSyntax item = ClassDeclaration(unitName) .AddModifiers(Token(SyntaxKind.PublicKeyword)) .AddBaseListTypes(SimpleBaseType(IdentifierName("ITonClient")), SimpleBaseType(IdentifierName("IDisposable"))) .AddMembers(fieldDeclaration) .AddMembers(constructorDeclaration) .AddMembers(propertyDeclarationSyntaxes) .AddMembers(disposeMethod); return(NamespaceDeclaration(IdentifierName(ClientGenerator.Namespace)) .AddMembers(item)); }
private static MemberDeclarationSyntax[] GetProperties(TonApi tonApi) { MemberDeclarationSyntax[] propertyDeclarationSyntaxes = tonApi.Modules .Select(module => { var formattedName = NamingConventions.Normalize(module.Name); var summary = module.Summary + (module.Description != null ? $"\n{module.Description}" : null); return(PropertyDeclaration(IdentifierName($"I{formattedName}Module"), formattedName) .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword).WithLeadingTrivia(CommentsHelpers.BuildCommentTrivia(summary)))) .WithAccessorList( AccessorList( List(new[] { AccessorDeclaration( SyntaxKind.GetAccessorDeclaration) .WithSemicolonToken( Token(SyntaxKind.SemicolonToken)) })))); }) .ToArray(); return(propertyDeclarationSyntaxes); }
public static Dictionary <string, string> MapNumericTypes(IEnumerable <Module> module) { return(module.SelectMany(m => m.Types).Where(t => t.Type == TypeType.Number) .Select(t => new { typeName = NamingConventions.Normalize(t.Name), sharpType = ConvertToSharpNumeric(t.NumberType, t.NumberSize) }) .ToDictionary(kv => kv.typeName, kv => kv.sharpType)); }
private static MemberDeclarationSyntax GetMethodDeclaration(Module module, Function function, bool withBody) { var responseType = function.Result.GetMethodReturnType(); var responseDeclaration = responseType == null ? "Task" : $"Task<{responseType}>"; var requestParam = new { name = default(string), type = default(string) }; var callbackParam = new { name = default(string), nameWithNull = default(string), type = default(string) }; foreach (Param param in function.Params) { if (param.Type == ParamType.Generic && param.GenericName == ParamGenericName.Arc) { GenericArg arcArg = param.GenericArgs[0]; if (arcArg.Type == GenericArgType.Ref && arcArg.RefName == "Request") { var name = StringUtils.EscapeReserved(function.Params[2].Name.GetEnumMemberValueOrString()); callbackParam = new { name, nameWithNull = $"{name} = null", type = string.Equals(module.Name, "net", StringComparison.OrdinalIgnoreCase) ? "JsonElement" : NamingConventions.EventFormatter(module.Name) }; } } if (param.Type == ParamType.Generic && param.GenericName == ParamGenericName.AppObject) { callbackParam = new { name = "appObject", nameWithNull = "appObject = null", type = "JsonElement" } } ; if (param.Name == Name.Params) { requestParam = new { name = StringUtils.EscapeReserved(function.Params[1].Name.GetEnumMemberValueOrString()), type = GetParamType(function.Params[1]) } } ; } var functionSummary = function.Summary + (function.Description != null ? $"\n{function.Description}" : null); var modifiers = new List <SyntaxToken> { Token(SyntaxKind.PublicKeyword).WithLeadingTrivia(CommentsHelpers.BuildCommentTrivia(functionSummary)) }; if (withBody) { modifiers.Add(Token(SyntaxKind.AsyncKeyword)); } var @params = new List <ParameterSyntax>(); var methodDeclarationParams = new List <ParameterSyntax>(); if (requestParam.name != default) { ParameterSyntax param = Parameter(Identifier(requestParam.name)).WithType(IdentifierName(requestParam.type)); methodDeclarationParams.Add(param); @params.Add(param); } if (callbackParam.name != default) { methodDeclarationParams.Add(Parameter(Identifier(callbackParam.nameWithNull)).WithType(IdentifierName($"Action<{callbackParam.type},uint>"))); @params.Add(Parameter(Identifier(callbackParam.name)).WithType(IdentifierName($"Action<{callbackParam.type},uint>"))); } MethodDeclarationSyntax method = MethodDeclaration(ParseTypeName(responseDeclaration), NamingConventions.Normalize(function.Name)) .AddParameterListParameters(methodDeclarationParams.ToArray()) .AddParameterListParameters(Parameter(Identifier("cancellationToken")) .WithType(IdentifierName(nameof(CancellationToken))) .WithDefault(EqualsValueClause(IdentifierName("default")))) .AddModifiers(modifiers.ToArray()); if (withBody) { var arguments = new List <ArgumentSyntax> { Argument(IdentifierName($"\"{module.Name}.{function.Name}\"")) }; arguments.AddRange( @params .Select(p => Argument(IdentifierName(p.Identifier.Text)))); arguments.Add(Argument(IdentifierName("cancellationToken"))); var genericParametersDeclaration = StringUtils.GetGenericParametersDeclaration(requestParam?.type, responseType, callbackParam?.type); AwaitExpressionSyntax awaitExpression = AwaitExpression( InvocationExpression(IdentifierName($"_tonClientAdapter.Request{genericParametersDeclaration}")) .AddArgumentListArguments(arguments.ToArray())); StatementSyntax ex = responseType == null ? ExpressionStatement(awaitExpression) : ReturnStatement(awaitExpression); BlockSyntax blockSyntax = Block(ex); return(method.WithBody(blockSyntax)); } return(method.WithSemicolonToken(Token(SyntaxKind.SemicolonToken))); }
public static NamespaceDeclarationSyntax CreateTonModuleClass(string unitName, Module module) { var moduleName = $"{unitName}Module"; StatementSyntax statementSyntax = ParseStatement("_tonClientAdapter = tonClientAdapter;"); VariableDeclarationSyntax variableDeclaration = VariableDeclaration(ParseTypeName("ITonClientAdapter")) .AddVariables(VariableDeclarator("_tonClientAdapter")); FieldDeclarationSyntax fieldDeclaration = FieldDeclaration(variableDeclaration) .AddModifiers(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ReadOnlyKeyword)); ConstructorDeclarationSyntax constructorDeclaration = ConstructorDeclaration(moduleName) .AddParameterListParameters( Parameter(Identifier("tonClientAdapter")).WithType(IdentifierName("ITonClientAdapter"))) .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) .WithBody(Block(statementSyntax)); var methods = module .Functions .Select(f => GetMethodDeclaration(module, f, true)) .ToArray(); ClassDeclarationSyntax item = ClassDeclaration(moduleName) .AddModifiers(Token(SyntaxKind.PublicKeyword)) .AddBaseListTypes(SimpleBaseType(IdentifierName(NamingConventions.ToInterfaceName(moduleName)))) .AddMembers(fieldDeclaration) .AddMembers(constructorDeclaration) .AddMembers(methods); return(NamespaceDeclaration(IdentifierName(ClientGenerator.NamespaceModules)) .AddMembers(item)); }
private static string GetParamType(Param param) { return(NamingConventions.Normalize(param.RefName)); }