1
- using Microsoft . CodeAnalysis . CSharp ;
2
- using Microsoft . CodeAnalysis . CSharp . Syntax ;
3
1
using Plugin ;
4
2
using SqlcGenCsharp . Drivers ;
5
3
using SqlcGenCsharp . Generators ;
8
6
using System . IO ;
9
7
using System . Linq ;
10
8
using System . Threading . Tasks ;
11
- using static Microsoft . CodeAnalysis . CSharp . SyntaxFactory ;
12
- using File = Plugin . File ;
13
9
14
10
namespace SqlcGenCsharp ;
15
11
16
12
public class CodeGenerator
17
13
{
18
- private static readonly string [ ] ResharperDisables =
19
- [
20
- "UnusedAutoPropertyAccessor.Global" ,
21
- "NotAccessedPositionalProperty.Global" ,
22
- "ConvertToUsingDeclaration" ,
23
- "UseAwaitUsing"
24
- ] ;
25
-
26
- private string ? _namespaceName ;
27
14
private Options ? _options ;
15
+ private Dictionary < string , Table > ? _tables ;
28
16
private DbDriver ? _dbDriver ;
29
- private DataClassesGen ? _dataClassesGen ;
30
- private RootGen ? _rootGen ;
17
+ private QueriesGen ? _queriesGen ;
18
+ private ModelsGen ? _modelsGen ;
31
19
private UtilsGen ? _utilsGen ;
32
20
private CsprojGen ? _csprojGen ;
33
21
34
- private void InitGenerators ( GenerateRequest generateRequest )
35
- {
36
- var outputDirectory = generateRequest . Settings . Codegen . Out ;
37
- var projectName = new DirectoryInfo ( outputDirectory ) . Name ;
38
- Options = new Options ( generateRequest ) ;
39
- NamespaceName = Options . NamespaceName == string . Empty ? projectName : Options . NamespaceName ;
40
- DbDriver = InstantiateDriver ( ) ;
41
-
42
- // initialize file generators
43
- CsprojGen = new CsprojGen ( outputDirectory , projectName , NamespaceName , 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
- }
54
-
55
22
private Options Options
56
23
{
57
24
get => _options ! ;
58
25
set => _options = value ;
59
26
}
60
27
28
+ private Dictionary < string , Table > Tables
29
+ {
30
+ get => _tables ! ;
31
+ set => _tables = value ;
32
+ }
33
+
61
34
private DbDriver DbDriver
62
35
{
63
36
get => _dbDriver ! ;
64
37
set => _dbDriver = value ;
65
38
}
66
39
67
- private DataClassesGen DataClassesGen
40
+ private QueriesGen QueriesGen
68
41
{
69
- get => _dataClassesGen ! ;
70
- set => _dataClassesGen = value ;
42
+ get => _queriesGen ! ;
43
+ set => _queriesGen = value ;
71
44
}
72
45
73
- private RootGen RootGen
46
+ private ModelsGen ModelsGen
74
47
{
75
- get => _rootGen ! ;
76
- set => _rootGen = value ;
48
+ get => _modelsGen ! ;
49
+ set => _modelsGen = value ;
77
50
}
78
51
79
52
private UtilsGen UtilsGen
@@ -88,13 +61,35 @@ private CsprojGen CsprojGen
88
61
set => _csprojGen = value ;
89
62
}
90
63
64
+ private void InitGenerators ( GenerateRequest generateRequest )
65
+ {
66
+ var outputDirectory = generateRequest . Settings . Codegen . Out ;
67
+ var projectName = new DirectoryInfo ( outputDirectory ) . Name ;
68
+ Options = new Options ( generateRequest ) ;
69
+
70
+ // TODO currently only default schema is considered - should consider all non-internal schemas
71
+ Tables = generateRequest . Catalog . Schemas
72
+ . Where ( schema => schema . Name == generateRequest . Catalog . DefaultSchema )
73
+ . SelectMany ( schema => schema . Tables )
74
+ . ToDictionary ( table => table . Rel . Name , table => table ) ;
75
+
76
+ var namespaceName = Options . NamespaceName == string . Empty ? projectName : Options . NamespaceName ;
77
+ DbDriver = InstantiateDriver ( ) ;
78
+
79
+ // initialize file generators
80
+ CsprojGen = new CsprojGen ( outputDirectory , projectName , namespaceName , Options ) ;
81
+ QueriesGen = new QueriesGen ( DbDriver , Options , namespaceName ) ;
82
+ ModelsGen = new ModelsGen ( DbDriver , Options , namespaceName ) ;
83
+ UtilsGen = new UtilsGen ( namespaceName , Options ) ;
84
+ }
85
+
91
86
private DbDriver InstantiateDriver ( )
92
87
{
93
88
return Options . DriverName switch
94
89
{
95
- DriverName . MySqlConnector => new MySqlConnectorDriver ( Options ) ,
96
- DriverName . Npgsql => new NpgsqlDriver ( Options ) ,
97
- DriverName . Sqlite => new SqliteDriver ( Options ) ,
90
+ DriverName . MySqlConnector => new MySqlConnectorDriver ( Options , Tables ) ,
91
+ DriverName . Npgsql => new NpgsqlDriver ( Options , Tables ) ,
92
+ DriverName . Sqlite => new SqliteDriver ( Options , Tables ) ,
98
93
_ => throw new ArgumentException ( $ "unknown driver: { Options . DriverName } ")
99
94
} ;
100
95
}
@@ -104,7 +99,8 @@ public Task<GenerateResponse> Generate(GenerateRequest generateRequest)
104
99
InitGenerators ( generateRequest ) ; // the request is necessary in order to know which generators are needed
105
100
var fileQueries = GetFileQueries ( ) ;
106
101
var files = fileQueries
107
- . Select ( fq => GenerateFile ( fq . Value , fq . Key ) )
102
+ . Select ( fq => QueriesGen . GenerateFile ( fq . Value , fq . Key ) )
103
+ . Append ( ModelsGen . GenerateFile ( Tables ) )
108
104
. Append ( UtilsGen . GenerateFile ( ) )
109
105
. AppendIf ( CsprojGen . GenerateFile ( ) , Options . GenerateCsproj ) ;
110
106
@@ -126,110 +122,4 @@ string QueryFilenameToClassName(string filenameWithExtension)
126
122
Path . GetExtension ( filenameWithExtension ) [ 1 ..] . ToPascalCase ( ) ) ;
127
123
}
128
124
}
129
-
130
- private File GenerateFile ( IEnumerable < Query > queries , string className )
131
- {
132
- var ( usingDirectives , classDeclaration ) = GenerateClass ( queries , className ) ;
133
- var root = RootGen . CompilationRootGen (
134
- IdentifierName ( NamespaceName ) , usingDirectives . ToArray ( ) , classDeclaration ) ;
135
- root = AddResharperDisables ( root ) ;
136
- root = root . AddCommentOnTop ( Consts . AutoGeneratedComment ) ;
137
-
138
- return new File
139
- {
140
- Name = $ "{ className } .cs",
141
- Contents = root . ToByteString ( )
142
- } ;
143
- }
144
-
145
- private static CompilationUnitSyntax AddResharperDisables ( CompilationUnitSyntax compilationUnit )
146
- {
147
- return ResharperDisables
148
- . Aggregate ( compilationUnit , ( current , resharperDisable ) =>
149
- current . AddCommentOnTop ( $ "// ReSharper disable { resharperDisable } ") ) ;
150
- }
151
-
152
- private ( IList < UsingDirectiveSyntax > , MemberDeclarationSyntax ) GenerateClass ( IEnumerable < Query > queries ,
153
- string className )
154
- {
155
- var usingDirectives = DbDriver . GetUsingDirectives ( ) ;
156
- var classMembers = queries . SelectMany ( GetMembersForSingleQuery ) ;
157
- return ( usingDirectives , GetClassDeclaration ( className , classMembers ) ) ;
158
- }
159
-
160
- private ClassDeclarationSyntax GetClassDeclaration ( string className ,
161
- IEnumerable < MemberDeclarationSyntax > classMembers )
162
- {
163
- var optionalDapperConfig = Options . UseDapper
164
- ? Environment . NewLine + " Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;"
165
- : "" ;
166
- var classDeclaration = ( ClassDeclarationSyntax ) ParseMemberDeclaration (
167
- $$ """
168
- class {{ className }}
169
- {
170
- public {{ className }} (string {{ Variable . ConnectionString . AsVarName ( ) }} )
171
- {
172
- this.{{ Variable . ConnectionString . AsPropertyName ( ) }} = {{ Variable . ConnectionString . AsVarName ( ) }} ;{{ optionalDapperConfig }}
173
- }
174
- private string {{ Variable . ConnectionString . AsPropertyName ( ) }} { get; }
175
- }
176
- """ ) !
177
- . AddModifiers ( Token ( SyntaxKind . PublicKeyword ) ) ;
178
-
179
- return classDeclaration . AddMembers ( classMembers . ToArray ( ) ) ;
180
- }
181
-
182
- private IEnumerable < MemberDeclarationSyntax > GetMembersForSingleQuery ( Query query )
183
- {
184
- return new List < MemberDeclarationSyntax > ( )
185
- . Append ( GetQueryTextConstant ( query ) )
186
- . AppendIfNotNull ( GetQueryColumnsDataclass ( query ) )
187
- . AppendIfNotNull ( GetQueryParamsDataclass ( query ) )
188
- . Append ( AddMethodDeclaration ( query ) ) ;
189
- }
190
-
191
- private MemberDeclarationSyntax ? GetQueryColumnsDataclass ( Query query )
192
- {
193
- return query . Columns . Count <= 0
194
- ? null
195
- : DataClassesGen . Generate ( query . Name , ClassMember . Row , query . Columns , Options ) ;
196
- }
197
-
198
- private MemberDeclarationSyntax ? GetQueryParamsDataclass ( Query query )
199
- {
200
- if ( query . Params . Count <= 0 ) return null ;
201
- var columns = query . Params . Select ( DbDriver . GetColumnFromParam ) . ToList ( ) ;
202
- return DataClassesGen . Generate ( query . Name , ClassMember . Args , columns , Options ) ;
203
- }
204
-
205
- private MemberDeclarationSyntax GetQueryTextConstant ( Query query )
206
- {
207
- return ParseMemberDeclaration (
208
- $ "private const string { query . Name } { ClassMember . Sql . Name ( ) } = \" { DbDriver . TransformQueryText ( query ) } \" ;")
209
- !
210
- . AppendNewLine ( ) ;
211
- }
212
-
213
- private MemberDeclarationSyntax AddMethodDeclaration ( Query query )
214
- {
215
- var queryTextConstant = GetInterfaceName ( ClassMember . Sql ) ;
216
- var argInterface = GetInterfaceName ( ClassMember . Args ) ;
217
- var returnInterface = GetInterfaceName ( ClassMember . Row ) ;
218
-
219
- return query . Cmd switch
220
- {
221
- ":exec" => DbDriver . ExecDeclare ( queryTextConstant , argInterface , query ) ,
222
- ":one" => DbDriver . OneDeclare ( queryTextConstant , argInterface , returnInterface , query ) ,
223
- ":many" => DbDriver . ManyDeclare ( queryTextConstant , argInterface , returnInterface , query ) ,
224
- ":execrows" => ( ( IExecRows ) DbDriver ) . ExecRowsDeclare ( queryTextConstant , argInterface , query ) ,
225
- ":execlastid" => ( ( IExecLastId ) DbDriver ) . ExecLastIdDeclare ( queryTextConstant , argInterface , query ) ,
226
- ":copyfrom" => ( ( ICopyFrom ) DbDriver ) . CopyFromDeclare ( queryTextConstant , argInterface , query ) ,
227
- _ => throw new NotImplementedException ( $ "{ query . Cmd } is not implemented")
228
- } ;
229
-
230
- string GetInterfaceName ( ClassMember classMemberType )
231
- {
232
- return $ "{ query . Name } { classMemberType . Name ( ) } ";
233
- }
234
- }
235
125
}
0 commit comments