1
- using Grpc . Core ;
2
- using Microsoft . CodeAnalysis . CSharp ;
3
- using Microsoft . CodeAnalysis . CSharp . Syntax ;
1
+ using Google . Protobuf ;
4
2
using Plugin ;
3
+ using RubyCodegen ;
5
4
using SqlcGenCsharp . Drivers ;
6
- using SqlcGenCsharp . Generators ;
7
5
using System ;
8
6
using System . Collections . Generic ;
9
7
using System . IO ;
10
8
using System . Linq ;
11
9
using System . Threading . Tasks ;
12
- using static Microsoft . CodeAnalysis . CSharp . SyntaxFactory ;
13
10
using File = Plugin . File ;
14
11
15
12
namespace SqlcGenCsharp ;
16
13
17
14
public class CodeGenerator
18
15
{
19
16
private static readonly char [ ] Separator = [ '/' ] ;
20
-
21
- private static readonly string [ ] ResharperDisables =
22
- [
23
- "InconsistentNaming" ,
24
- "UnusedAutoPropertyAccessor.Global" ,
25
- "NotAccessedPositionalProperty.Global"
26
- ] ;
27
-
28
- private string ? _namespaceName ;
29
17
private Options ? _options ;
30
18
private DbDriver ? _dbDriver ;
31
- private DataClassesGen ? _dataClassesGen ;
32
- private RootGen ? _rootGen ;
33
- private UtilsGen ? _utilsGen ;
34
- private CsprojGen ? _csprojGen ;
35
19
36
20
private void InitGenerators ( GenerateRequest generateRequest )
37
21
{
38
22
Options = new Options ( generateRequest ) ;
39
- NamespaceName = GenerateNamespace ( generateRequest ) ;
40
23
DbDriver = InstantiateDriver ( ) ;
41
-
42
- // initialize file generators
43
- CsprojGen = new CsprojGen ( generateRequest . Settings . Codegen . Out , Options ) ;
44
- RootGen = new RootGen ( Options ) ;
45
- UtilsGen = new UtilsGen ( NamespaceName , Options ) ;
46
- DataClassesGen = new DataClassesGen ( DbDriver ) ;
47
- }
48
-
49
- private string NamespaceName
50
- {
51
- get => _namespaceName ! ;
52
- set => _namespaceName = value ;
53
24
}
54
25
55
26
private Options Options
@@ -64,36 +35,12 @@ private DbDriver DbDriver
64
35
set => _dbDriver = value ;
65
36
}
66
37
67
- private DataClassesGen DataClassesGen
68
- {
69
- get => _dataClassesGen ! ;
70
- set => _dataClassesGen = value ;
71
- }
72
-
73
- private RootGen RootGen
74
- {
75
- get => _rootGen ! ;
76
- set => _rootGen = value ;
77
- }
78
-
79
- private UtilsGen UtilsGen
80
- {
81
- get => _utilsGen ! ;
82
- set => _utilsGen = value ;
83
- }
84
-
85
- private CsprojGen CsprojGen
86
- {
87
- get => _csprojGen ! ;
88
- set => _csprojGen = value ;
89
- }
90
-
91
38
private DbDriver InstantiateDriver ( )
92
39
{
93
40
return Options . DriverName switch
94
41
{
95
- DriverName . MySqlConnector => new MySqlConnectorDriver ( Options . DotnetFramework ) ,
96
- DriverName . Npgsql => new NpgsqlDriver ( Options . DotnetFramework ) ,
42
+ DriverName . Mysql2 => new Mysql2Driver ( ) ,
43
+ DriverName . Pg => new PgDriver ( ) ,
97
44
_ => throw new ArgumentException ( $ "unknown driver: { Options . DriverName } ")
98
45
} ;
99
46
}
@@ -104,8 +51,7 @@ public Task<GenerateResponse> Generate(GenerateRequest generateRequest)
104
51
var fileQueries = GetFileQueries ( ) ;
105
52
var files = fileQueries
106
53
. Select ( fq => GenerateFile ( fq . Value , fq . Key ) )
107
- . Append ( UtilsGen . GenerateFile ( ) )
108
- . AppendIf ( CsprojGen . GenerateFile ( ) , Options . GenerateCsproj ) ;
54
+ . Append ( GenerateGemfile ( ) ) ;
109
55
110
56
return Task . FromResult ( new GenerateResponse { Files = { files } } ) ;
111
57
@@ -138,116 +84,99 @@ private string GenerateNamespace(GenerateRequest generateRequest)
138
84
139
85
private File GenerateFile ( IEnumerable < Query > queries , string className )
140
86
{
141
- var ( usingDirectives , classDeclaration ) = GenerateClass ( queries , className ) ;
142
- var root = RootGen . CompilationRootGen (
143
- IdentifierName ( NamespaceName ) , usingDirectives , classDeclaration ) ;
144
- root = AddResharperDisables ( root ) ;
145
- root = root . AddCommentOnTop ( Consts . AutoGeneratedComment ) ;
87
+ var ( requiredGems , classDeclaration ) = GenerateClass ( queries , className ) ;
88
+ var contents = $ """
89
+ { Consts . AutoGeneratedComment }
90
+ { requiredGems . Select ( r => r . Build ( ) ) . JoinByNewLine ( ) }
91
+
92
+ { classDeclaration . Build ( ) }
93
+ """ ;
146
94
147
95
return new File
148
96
{
149
- Name = $ "{ className } .cs ",
150
- Contents = root . ToByteString ( )
97
+ Name = $ "{ className . SnakeCase ( ) } .rb ",
98
+ Contents = ByteString . CopyFromUtf8 ( contents )
151
99
} ;
152
100
}
153
101
154
- private static CompilationUnitSyntax AddResharperDisables ( CompilationUnitSyntax compilationUnit )
102
+ private File GenerateGemfile ( )
155
103
{
156
- return ResharperDisables
157
- . Aggregate ( compilationUnit , ( current , resharperDisable ) =>
158
- current . AddCommentOnTop ( $ "// ReSharper disable { resharperDisable } ") ) ;
159
- }
104
+ var requireGems = DbDriver . GetRequiredGems ( ) . Select ( gem => $ "gem '{ gem . GetName ( ) } '") . JoinByNewLine ( ) ;
105
+ return new File
106
+ {
107
+ Name = "Gemfile" ,
108
+ Contents = ByteString . CopyFromUtf8 ( $ """
109
+ source 'https://rubygems.org'
160
110
161
- private ( UsingDirectiveSyntax [ ] , MemberDeclarationSyntax ) GenerateClass ( IEnumerable < Query > queries ,
162
- string className )
163
- {
164
- var usingDirectives = DbDriver . GetUsingDirectives ( ) ;
165
- var classMembers = queries . SelectMany ( GetMembersForSingleQuery ) . ToArray ( ) ;
166
- return ( usingDirectives , GetClassDeclaration ( className , classMembers ) ) ;
111
+ { requireGems }
112
+ """ )
113
+ } ;
167
114
}
168
115
169
- private ClassDeclarationSyntax GetClassDeclaration ( string className ,
170
- IEnumerable < MemberDeclarationSyntax > classMembers )
116
+ private ( IEnumerable < RequireGem > , ClassDeclaration ) GenerateClass ( IEnumerable < Query > queries , string className )
171
117
{
172
- var classDeclaration = ( ClassDeclarationSyntax ) ( Options . DotnetFramework . LatestDotnetSupported ( )
173
- ? GetWithPrimaryConstructor ( )
174
- : GetWithRegularConstructor ( ) ) ;
175
- return classDeclaration . AddMembers ( classMembers . ToArray ( ) ) ;
176
-
177
- MemberDeclarationSyntax GetWithPrimaryConstructor ( )
178
- {
179
- return ParseMemberDeclaration (
180
- $ "class { className } (string { Variable . ConnectionString . Name ( ) } )" + "{}" ) !
181
- . AddModifiers ( Token ( SyntaxKind . PublicKeyword ) ) ;
182
- }
183
-
184
- MemberDeclarationSyntax GetWithRegularConstructor ( )
185
- {
186
- return ParseMemberDeclaration (
187
- $$ """
188
- class {{ className }}
189
- {
190
- public {{ className }} (string {{ Variable . ConnectionString . Name ( ) }} )
191
- {
192
- this.{{ Variable . ConnectionString . Name ( ) }} = {{ Variable . ConnectionString . Name ( ) }} ;
193
- }
194
- private string {{ Variable . ConnectionString . Name ( ) }} { get; }
195
- }
196
- """ ) !
197
- . AddModifiers ( Token ( SyntaxKind . PublicKeyword ) ) ;
198
- }
118
+ var requiredGems = DbDriver . GetRequiredGems ( ) ;
119
+ var initMethod = DbDriver . GetInitMethod ( ) ;
120
+ var queryMembers = queries
121
+ . SelectMany ( q =>
122
+ {
123
+ IEnumerable < IComposable > members = new List < IComposable > ( ) ;
124
+ members = members . Append ( GetQueryTextConstant ( q ) ) ;
125
+ members = members . AppendIfNotNull ( GetQueryColumnsDataclass ( q ) ) ;
126
+ members = members . AppendIfNotNull ( GetQueryParamsDataclass ( q ) ) ;
127
+ members = members . Append ( GetMethodDeclaration ( q ) ) ;
128
+ return members ;
129
+ } ) ;
130
+ var classMembers = new [ ] { initMethod } . Concat ( queryMembers ) ;
131
+ return ( requiredGems , new ClassDeclaration ( className , classMembers ) ) ;
199
132
}
200
133
201
- private MemberDeclarationSyntax [ ] GetMembersForSingleQuery ( Query query )
134
+ private static SimpleStatement GenerateDataclass ( string name , ClassMember classMember , IEnumerable < Column > columns ,
135
+ Options options )
202
136
{
203
- return new [ ]
204
- {
205
- GetQueryTextConstant ( query ) ,
206
- GetQueryColumnsDataclass ( query ) ,
207
- GetQueryParamsDataclass ( query ) ,
208
- AddMethodDeclaration ( query )
209
- }
210
- . Where ( member => member != null )
211
- . Cast < MemberDeclarationSyntax > ( )
212
- . ToArray ( ) ;
137
+ var dataclassName = $ "{ name . FirstCharToUpper ( ) } { classMember . Name ( ) } ";
138
+ var dataColumns = columns . Select ( c => $ ":{ c . Name . ToLower ( ) } ") . JoinByCommaAndNewLine ( ) ;
139
+ return new SimpleStatement ( dataclassName ,
140
+ new SimpleExpression ( options . RubyMajorVersion . LatestRubySupported ( )
141
+ ? $ "Struct.new(\n { dataColumns . Indent ( ) } \n )"
142
+ : $ "Data.define(\n { dataColumns . Indent ( ) } \n )") ) ;
213
143
}
214
144
215
- private MemberDeclarationSyntax ? GetQueryColumnsDataclass ( Query query )
145
+ private SimpleStatement ? GetQueryColumnsDataclass ( Query query )
216
146
{
147
+ if ( query . Columns . Count <= 0 ) return null ;
217
148
return query . Columns . Count <= 0
218
149
? null
219
- : DataClassesGen . Generate ( query . Name , ClassMember . Row , query . Columns , Options ) ;
150
+ : GenerateDataclass ( query . Name , ClassMember . Row , query . Columns , Options ) ;
220
151
}
221
152
222
- private MemberDeclarationSyntax ? GetQueryParamsDataclass ( Query query )
153
+ private SimpleStatement ? GetQueryParamsDataclass ( Query query )
223
154
{
224
155
if ( query . Params . Count <= 0 ) return null ;
225
156
var columns = query . Params . Select ( p => p . Column ) ;
226
- return DataClassesGen . Generate ( query . Name , ClassMember . Args , columns , Options ) ;
157
+ return GenerateDataclass ( query . Name , ClassMember . Args , columns , Options ) ;
227
158
}
228
159
229
- private MemberDeclarationSyntax GetQueryTextConstant ( Query query )
160
+ private static SimpleStatement GetQueryTextConstant ( Query query )
230
161
{
231
- return ParseMemberDeclaration (
232
- $ "private const string { query . Name } { ClassMember . Sql . Name ( ) } = \" { DbDriver . TransformQueryText ( query ) } \" ;")
233
- !
234
- . AppendNewLine ( ) ;
162
+ return new SimpleStatement ( $ "{ query . Name } { ClassMember . Sql } ", new SimpleExpression ( $ "%q({ query . Text } )") ) ;
235
163
}
236
164
237
- private MemberDeclarationSyntax AddMethodDeclaration ( Query query )
165
+ private MethodDeclaration GetMethodDeclaration ( Query query )
238
166
{
239
167
var queryTextConstant = GetInterfaceName ( ClassMember . Sql ) ;
240
- var argInterface = GetInterfaceName ( ClassMember . Args ) ;
168
+ var argInterface = GetInterfaceName ( ClassMember . Args ) . SnakeCase ( ) ;
241
169
var returnInterface = GetInterfaceName ( ClassMember . Row ) ;
170
+ var funcName = query . Name . SnakeCase ( ) ;
242
171
243
172
return query . Cmd switch
244
173
{
245
- ":exec" => DbDriver . ExecDeclare ( query . Name , queryTextConstant , argInterface , query . Params ) ,
246
- ":one" => DbDriver . OneDeclare ( query . Name , queryTextConstant , argInterface , returnInterface ,
174
+ ":one" => DbDriver . OneDeclare ( funcName , queryTextConstant , argInterface , returnInterface ,
247
175
query . Params , query . Columns ) ,
248
- ":many" => DbDriver . ManyDeclare ( query . Name , queryTextConstant , argInterface , returnInterface ,
176
+ ":many" => DbDriver . ManyDeclare ( funcName , queryTextConstant , argInterface , returnInterface ,
249
177
query . Params , query . Columns ) ,
250
- ":execlastid" => DbDriver . ExecLastIdDeclare ( query . Name , queryTextConstant , argInterface , query . Params ) ,
178
+ ":exec" => DbDriver . ExecDeclare ( funcName , queryTextConstant , argInterface , query . Params ) ,
179
+ ":execlastid" => DbDriver . ExecLastIdDeclare ( funcName , queryTextConstant , argInterface , query . Params ) ,
251
180
_ => throw new InvalidDataException ( )
252
181
} ;
253
182
0 commit comments