2
0

fpddcodegen.pp 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2007 by Michael Van Canneyt, member of the
  4. Free Pascal development team
  5. Data Dictionary Code Generator Implementation.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit FPDDCodeGen;
  13. {$mode objfpc}{$H+}
  14. interface
  15. uses
  16. Classes, SysUtils, DB, fpDataDict;
  17. Type
  18. TPropType = (ptAuto,
  19. ptBoolean,
  20. ptShortint, ptByte,
  21. ptSmallInt, ptWord,
  22. ptLongint, ptCardinal,
  23. ptInt64, ptQWord,
  24. ptShortString, ptAnsiString, ptWideString, ptUnicodeString, ptUtf8String,
  25. ptSingle, ptDouble, ptExtended, ptComp, ptCurrency,
  26. ptDateTime,
  27. ptEnumerated, ptSet, ptStream, ptTStrings,
  28. ptCustom);
  29. TVisibility = (vPrivate,vProtected,vPublic,vPublished);
  30. TVisibilities = Set of TVisibility;
  31. TPropAccess = (paReadWrite,paReadonly,paWriteonly);
  32. TPropSetter = (psRead,psWrite);
  33. TPropSetters = set of TPropSetter;
  34. TFieldPropDefs = Class;
  35. { TFieldPropDef }
  36. TFieldPropDef = Class (TCollectionItem)
  37. private
  38. FEnabled: Boolean;
  39. FFieldName: String;
  40. FFieldType: TFieldType;
  41. FPropAccess: TPropAccess;
  42. FPropDef: String;
  43. FPropSetters: TPropSetters;
  44. FPropType : TPropType;
  45. FPRopSize: Integer;
  46. FPropName : String;
  47. FPropVis: TVisibility;
  48. function GetPropName: String;
  49. function GetPropType: TPropType;
  50. function GetPropTypeStored: boolean;
  51. Protected
  52. Procedure InitFromField(F : TField); virtual;
  53. Procedure InitFromDDFieldDef(F : TDDFieldDef);virtual;
  54. procedure SetFieldType(AValue: TFieldType); virtual;
  55. procedure SetPropName(const AValue: String); virtual;
  56. Public
  57. Constructor Create(ACollection : TCollection) ; override;
  58. Procedure Assign(ASource : TPersistent); override;
  59. Function FieldPropDefs : TFieldPropDefs;
  60. Function HasGetter : Boolean; Virtual; // Checks Propsetters for psRead
  61. Function HasSetter : Boolean; Virtual; // True for streams/strings or if Propsetters has pswrite
  62. Function ObjPasTypeDef : String; virtual; // Object pascal definition of type
  63. Function ObjPasReadDef : String; virtual; // Object pascal definition of getter
  64. Function ObjPasWriteDef : String; virtual; // Object pascal definition of setter
  65. Published
  66. Property Enabled : Boolean Read FEnabled Write FEnabled;
  67. Property FieldName : String Read FFieldName Write FFieldName;
  68. Property FieldType : TFieldType Read FFieldType Write SetFieldType;
  69. Property PropertyName : String Read GetPropName Write SetPropName;
  70. Property PropertyType : TPropType Read GetPropType Write FPropType Stored GetPropTypeStored;
  71. Property PropertySize : Integer Read FPRopSize Write FPropSize;
  72. Property PropertyDef : String Read FPropDef Write FPropDef;
  73. Property PropertyVisibility : TVisibility Read FPropVis Write FPropVis;
  74. Property PropertyAccess : TPropAccess Read FPropAccess Write FPropAccess;
  75. Property PropSetters : TPropSetters Read FPropSetters Write FPropSetters;
  76. end;
  77. { TFieldPropDefs }
  78. TFieldPropDefs = Class (TCollection)
  79. private
  80. function GetPropDef(Index : integer): TFieldPropDef;
  81. procedure SetPropDef(Index : integer; const AValue: TFieldPropDef);
  82. Public
  83. Function AddDef(AName : String) : TFieldPropDef;
  84. Procedure FromDataset(Dataset : TDataset; DoClear : Boolean = True);
  85. Procedure FromDDFieldDefs(Defs : TDDFieldDefs; DoClear : Boolean = True);
  86. Function IndexOfPropName(AName : String) : Integer;
  87. Function IndexOfFieldName(AName : String) : Integer;
  88. Function FindPropName(AName : String) : TFieldPropDef;
  89. Function FindFieldName(AName : String) : TFieldPropDef;
  90. Property PropDefs[Index : integer] : TFieldPropDef Read GetPropDef write SetPropDef; Default;
  91. end;
  92. { TFieldPropDefs }
  93. TCodeOption = (coInterface,coImplementation,coUnit);
  94. TCodeOptions = Set of TCodeOption;
  95. { TCodeGeneratorOptions }
  96. TCodeGeneratorOptions = Class(TPersistent)
  97. private
  98. FImplementationUnits: String;
  99. FInterfaceUnits: String;
  100. FOptions: TCodeOptions;
  101. FUnitName: String;
  102. FExtraSetterLine : string;
  103. procedure SetImplementationUnits(const AValue: String);
  104. procedure SetInterfaceUnits(const AValue: String);
  105. procedure SetUnitname(const AValue: String);
  106. Protected
  107. procedure SetOPtions(const AValue: TCodeOptions); virtual;
  108. Public
  109. Constructor create; virtual;
  110. Procedure Assign(ASource : TPersistent); override;
  111. Published
  112. // Line of code that will be added to each property setter. Use %PROPNAME% to include property name in the line.
  113. Property ExtraSetterLine : String Read FExtraSetterLine Write FExtraSetterLine;
  114. // options
  115. Property Options : TCodeOptions Read FOptions Write SetOPtions;
  116. // Name of unit if a unit is generated.
  117. Property UnitName : String Read FUnitName Write SetUnitname;
  118. // Comma-separated list of units that will be put in the interface units clause
  119. Property InterfaceUnits : String Read FInterfaceUnits Write SetInterfaceUnits;
  120. // Comma-separated list of units that will be put in the implementation units clause
  121. Property ImplementationUnits : String Read FImplementationUnits Write SetImplementationUnits;
  122. end;
  123. TCodeGeneratorOptionsClass = Class of TCodeGeneratorOptions;
  124. { TDDCustomCodeGenerator }
  125. TCodeEvent = Procedure(Sender : TObject; Strings : TStrings) of object;
  126. TDDCustomCodeGenerator = Class(TComponent)
  127. FCodeOptions: TCodeGeneratorOptions;
  128. Private
  129. FIndent: Integer;
  130. FCurrentIndent :String;
  131. Protected
  132. // Utility routines to add lines to the code. Will prepend indent.
  133. procedure AddLn(Strings: TStrings); overload;
  134. procedure AddLn(Strings: TStrings; Line: String); overload;
  135. procedure AddLn(Strings: TStrings; Fmt: String; Args: array of const); overload;
  136. // Create a pascal code string. Surround by quotes or not
  137. Function CreatePascalString(S : String; Quote : Boolean = True) : String;
  138. // Increase indent by defined amount
  139. procedure IncIndent;
  140. // Decrease indent by defined amount
  141. procedure DecIndent;
  142. // Start a method implementation. Writes the declaration. No Begin.
  143. procedure BeginMethod(STrings: TStrings; const Decl: String); Virtual;
  144. // End a method implementation. Writes the final end;
  145. procedure EndMethod(STrings: TStrings; const Decl: String);Virtual;
  146. // The following must be overridden by descendents
  147. Procedure DoGenerateInterface(Strings: TStrings); virtual;
  148. Procedure DoGenerateImplementation(Strings: TStrings); virtual;
  149. // Override this to return an instance of the proper class.
  150. Function CreateOptions : TCodeGeneratorOptions; virtual;
  151. // Override to return minimal uses clause for interface section.
  152. Function GetInterfaceUsesClause : String; virtual;
  153. // Override to return minimal uses clause for implementation section.
  154. Function GetImplementationUsesClause : String; virtual;
  155. // Must override to return real fielddefs
  156. function GetFieldDefs: TFieldPropDefs; virtual;
  157. // Must override to return real fielddefs
  158. procedure SetFieldDefs(const AValue: TFieldPropDefs); virtual;
  159. // Must override to return real SQL
  160. function GetSQL: TStrings; virtual;
  161. // Must override to set real SQL
  162. procedure SetSQL(const AValue: TStrings); virtual;
  163. Public
  164. Constructor Create(AOWner : TComponent); override;
  165. Destructor Destroy; override;
  166. Procedure GenerateCode(Stream : TStream);
  167. Procedure GenerateCode(Strings: TStrings);
  168. Class Function NeedsSQL : Boolean; virtual;
  169. Class Function NeedsFieldDefs : Boolean; virtual;
  170. Function ShowConfigDialog : Boolean;
  171. Property Fields : TFieldPropDefs Read GetFieldDefs Write SetFieldDefs;
  172. Property SQL : TStrings Read GetSQL Write SetSQL;
  173. Published
  174. Property CodeOptions : TCodeGeneratorOptions Read FCodeOptions Write FCodeOptions;
  175. Property Indent : Integer Read FIndent Write FIndent Default 2;
  176. end;
  177. { TClassCodeGeneratorOptions }
  178. TClassCodeGeneratorOptions = Class(TCodeGeneratorOptions)
  179. private
  180. FAncestorClass: String;
  181. FClassName: String;
  182. procedure SetAncestorClass(const AValue: String);
  183. Protected
  184. procedure SetClassName(const AValue: String); virtual;
  185. // Set to default value. Publish if needed.
  186. Property AncestorClass : String Read FAncestorClass Write SetAncestorClass;
  187. Public
  188. Procedure Assign(ASource : TPersistent); override;
  189. // Classname without T prepended
  190. Function CleanObjectClassName : String;
  191. Published
  192. Property ObjectClassName : String Read FClassName Write SetClassName;
  193. end;
  194. { TDDClassCodeGenerator }
  195. TDDClassCodeGenerator = Class(TDDCustomCodeGenerator)
  196. private
  197. FAfterClassDeclaration: TCodeEvent;
  198. FAfterClassImplementation: TCodeEvent;
  199. FAfterDestructOrImplementation: TCodeEvent;
  200. FAfterTypeSection: TCodeEvent;
  201. FAncestorClass : String;
  202. FBeforeClassDeclaration: TCodeEvent;
  203. FBeforeClassImplementation: TCodeEvent;
  204. FBeforeConstructOrImplementation: TCodeEvent;
  205. FBeforeTypeSection: TCodeEvent;
  206. FFieldDefs: TFieldPropDefs;
  207. FStreamClass: String;
  208. FStringsClass: String;
  209. FUnitName: String;
  210. procedure DoBeforeGetter(Strings: TStrings);
  211. function GetOpts: TClassCodeGeneratorOptions;
  212. procedure SetAncestorClass(const AValue: String);
  213. procedure SetClassName(const AValue: String);
  214. procedure SetUnitname(const AValue: String);
  215. Protected
  216. // Overrides from base class
  217. Function GetFieldDefs: TFieldPropDefs; override;
  218. procedure SetFieldDefs(const AValue: TFieldPropDefs); override;
  219. Function CreateOptions : TCodeGeneratorOptions; override;
  220. Procedure DoBeforeTypeSection(Strings: TStrings); virtual;
  221. Procedure DoAfterTypeSection(Strings: TStrings); virtual;
  222. Procedure DoBeforeClassDeclaration(Strings: TStrings); virtual;
  223. Procedure DoAfterClassDeclaration(Strings: TStrings); virtual;
  224. Procedure DoBeforeConstructor(Strings: TStrings); virtual;
  225. Procedure DoAfterDestructor(Strings: TStrings); virtual;
  226. Procedure DoBeforeClassImplementation(Strings : TStrings); virtual;
  227. Procedure DoAfterClassImplementation(Strings: TStrings); virtual;
  228. Procedure DoGenerateInterface(Strings: TStrings); override;
  229. Procedure DoGenerateImplementation(Strings: TStrings); override;
  230. // Override this if you want to add interfaces to the class.
  231. Function GetClassInterfaces : String; virtual;
  232. // General code things.
  233. // Override to create TFieldpropdefs descendent instance.
  234. Function CreateFieldPropDefs : TFieldPropDefs; virtual;
  235. // Set to default value. Publish if needed.
  236. //
  237. // Interface routines
  238. //
  239. // Write property getter implementation
  240. procedure WritePropertyGetterImpl(Strings: TStrings; F: TFieldPropDef); virtual;
  241. // Write property setter implementation
  242. procedure WritePropertySetterImpl(Strings: TStrings; F: TFieldPropDef); virtual;
  243. // Create class declaration.
  244. procedure CreateDeclaration(Strings: TStrings); virtual;
  245. // Create class head. Override to add after class start.
  246. procedure CreateClassHead(Strings: TStrings); virtual;
  247. // Create class end. Override to add before class end.
  248. procedure CreateClassEnd(Strings : TStrings); virtual;
  249. // Called right after section start is written.
  250. procedure WriteVisibilityStart(V: TVisibility; Strings: TStrings); virtual;
  251. // Called at the end of section.
  252. procedure WriteVisibilityEnd(V: TVisibility; Strings: TStrings); virtual;
  253. // Should a property declaration be written ? Checks enabled and visibility
  254. function AllowPropertyDeclaration(F: TFieldPropDef; AVisibility: TVisibilities): Boolean; virtual;
  255. // Writes a property declaration. Only called if AllowPropertyDeclaration returned true
  256. procedure WritePropertyDeclaration(Strings: TStrings; F: TFieldPropDef); virtual;
  257. // Creates a property declaration.
  258. Function PropertyDeclaration(Strings: TStrings; Def: TFieldPropDef) : String; virtual;
  259. // Writes private fields for class.
  260. procedure WritePrivateFields(Strings: TStrings); virtual;
  261. //
  262. // Implementation routines
  263. //
  264. // Create class implementation
  265. procedure CreateImplementation(Strings: TStrings); virtual;
  266. // Write implementation of constructor
  267. procedure WriteConstructorImplementation(Strings: TStrings); Virtual;
  268. // Write implementation of Destructor
  269. procedure WriteDestructorImplementation(Strings: TStrings); Virtual;
  270. // Write initialization of property (in constructor)
  271. procedure WriteFieldCreate(Strings: TStrings; F: TFieldPropDef); Virtual;
  272. // Write Finalization of property (in destructor)
  273. procedure WriteFieldDestroy(Strings: TStrings; F: TFieldPropDef); Virtual;
  274. //
  275. // Routines used in both Implementation/Interface
  276. //
  277. // Write property getter declaration
  278. Function PropertyGetterDeclaration(Def: TFieldPropDef; Impl : Boolean) : String; virtual;
  279. // Write property setter declaration
  280. Function PropertySetterDeclaration(Def: TFieldPropDef; Impl : Boolean) : String; virtual;
  281. // Determines whether a constructor/destructor pair is written.
  282. // By default one is written if ptStream/ptStrings is detected.
  283. Function NeedsConstructor : Boolean; virtual;
  284. // By default, this calls NeedsConstructor.
  285. Function NeedsDestructor : Boolean; virtual;
  286. // Override this to return the constructor declaration.
  287. Function ConstructorDeclaration(Impl : Boolean) : String; Virtual;
  288. // Override this to return the destructor declaration
  289. Function DestructorDeclaration(Impl : Boolean) : String; Virtual;
  290. //
  291. // Properties
  292. //
  293. // Class name used to instantiate TStrings instances.
  294. Property StringsClass : String Read FStringsClass Write FStringsClass;
  295. // Class name used to instantiate TStream instances.
  296. Property StreamClass : String Read FStreamClass Write FStreamClass;
  297. // Easy access to options
  298. Property ClassOptions : TClassCodeGeneratorOptions Read GetOpts;
  299. Public
  300. Constructor Create(AOwner : TComponent); override;
  301. Destructor Destroy; override;
  302. Procedure GenerateClass(Strings : TStrings); virtual;
  303. Procedure GenerateClass(Stream : TStream);
  304. Published
  305. Property Fields;
  306. Property AfterTypeSection : TCodeEvent Read FAfterTypeSection Write FAfterTypeSection;
  307. Property BeforeTypeSection : TCodeEvent Read FBeforeTypeSection Write FBeforeTypeSection;
  308. Property AfterClassDeclaration : TCodeEvent Read FAfterClassDeclaration Write FAfterClassDeclaration;
  309. Property BeforeClassDeclaration : TCodeEvent Read FBeforeClassDeclaration Write FBeforeClassDeclaration;
  310. Property AfterClassImplementation : TCodeEvent Read FAfterClassImplementation Write FAfterClassImplementation;
  311. Property BeforeClassImplementation : TCodeEvent Read FBeforeClassImplementation Write FBeforeClassImplementation;
  312. Property AfterDestructorImplementation : TCodeEvent Read FAfterDestructOrImplementation Write FAfterDestructOrImplementation;
  313. Property BeforeConstructorImplementation : TCodeEvent Read FBeforeConstructOrImplementation Write FBeforeConstructOrImplementation;
  314. end;
  315. ECodeGenerator = Class(Exception);
  316. { TExportFormatItem }
  317. TDDCustomCodeGeneratorClass = Class of TDDCustomCodeGenerator;
  318. TCodeGeneratorConfigureEvent = Function (Generator : TDDCustomCodeGenerator) : Boolean of object;
  319. { TCodeGeneratorItem }
  320. TCodeGeneratorItem = Class(TCollectionItem)
  321. private
  322. FClass: TDDCustomCodeGeneratorClass;
  323. FDescription: String;
  324. FName: String;
  325. FOnConfigure: TCodeGeneratorConfigureEvent;
  326. Procedure SetName(const AValue: String);
  327. Public
  328. Property GeneratorClass : TDDCustomCodeGeneratorClass Read FClass Write FClass;
  329. Published
  330. Property Name : String Read FName Write SetName;
  331. Property Description : String Read FDescription Write FDescription;
  332. Property OnConfigureDialog : TCodeGeneratorConfigureEvent Read FOnConfigure Write FOnConfigure;
  333. end;
  334. { TCodeGenerators }
  335. TCodeGenerators = Class(TCollection)
  336. private
  337. function GetGen(Index : Integer): TCodeGeneratorItem;
  338. procedure SetGen(Index : Integer; const AValue: TCodeGeneratorItem);
  339. Public
  340. // Registration/Unregistration
  341. Function RegisterCodeGenerator(Const AName, ADescription : String; AClass : TDDCustomCodeGeneratorClass) : TCodeGeneratorItem;
  342. Procedure UnRegisterCodeGenerator(AClass : TDDCustomCodeGeneratorClass);
  343. Procedure UnRegisterCodeGenerator(Const AName : String);
  344. // Searching
  345. Function IndexOfCodeGenerator(Const AName : String): Integer;
  346. Function IndexOfCodeGenerator(AClass : TDDCustomCodeGeneratorClass): Integer;
  347. Function FindCodeGenerator(Const AName : String) : TCodeGeneratorItem;
  348. Function FindCodeGenerator(AClass : TDDCustomCodeGeneratorClass) : TCodeGeneratorItem;
  349. // Shows configuration dialog, if one was configured for this class
  350. Function ConfigureCodeGenerator(AGenerator : TDDCustomCodeGenerator) : Boolean;
  351. Function GeneratorByName(Const AName : String) : TCodeGeneratorItem;
  352. Property Generators[Index : Integer] : TCodeGeneratorItem Read GetGen Write SetGen; default;
  353. end;
  354. Function CodeGenerators : TCodeGenerators;
  355. // Easy access functions
  356. Function RegisterCodeGenerator(Const AName,ADescription : String; AClass : TDDCustomCodeGeneratorClass) : TCodeGeneratorItem;
  357. Procedure UnRegisterCodeGenerator(AClass : TDDCustomCodeGeneratorClass);
  358. Procedure UnRegisterCodeGenerator(Const AName : String);
  359. Type
  360. TFieldPropTypeMap = Array[TFieldType] of TPropType;
  361. TPropertyVisibilityMap = Array[TPropType] of TVisibility;
  362. Var
  363. FieldToPropTypeMap : TFieldPropTypeMap = (
  364. ptCustom, ptAnsiString, ptSmallInt, ptLongInt, ptWord,
  365. ptBoolean, ptDouble, ptCurrency, ptCurrency, ptDateTime, ptDateTime, ptDateTime,
  366. ptCustom, ptCustom, ptLongInt, ptStream, ptTStrings, ptStream, ptTStrings,
  367. ptCustom, ptCustom, ptCustom, ptCustom, ptAnsiString,
  368. ptWideString, ptInt64, ptCustom, ptCustom, ptCustom,
  369. ptCustom, ptCustom, ptCustom, ptCustom, ptCustom,
  370. ptCustom, ptAnsiString, ptDateTime, ptCurrency, ptWideString, ptWideString,
  371. ptDateTime, ptDateTime, ptCustom, ptCustom, ptCustom, ptCustom);
  372. PropTypeToVisibilityMap : TPropertyVisibilityMap = (
  373. vPrivate,
  374. vPublished,
  375. vPublished, vPublished,
  376. vPublished, vPublished,
  377. vPublished, vPublished,
  378. vPublished, vPublished,
  379. vPublished, vPublished, vPublished, vPublished, vPublished,
  380. vPublished, vPublished, vPublished, vPublished, vPublished,
  381. vPublished,
  382. vPublished, vPublished, vPublic, vPublished,
  383. vPrivate);
  384. Const
  385. ptInteger = ptLongint;
  386. ptString = ptAnsiString;
  387. Const
  388. PropTypeNames : Array[TPropType] of string
  389. = ('',
  390. 'Boolean',
  391. 'ShortInt', 'Byte',
  392. 'SmallInt', 'Word',
  393. 'Longint', 'Cardinal',
  394. 'Int64', 'QWord',
  395. 'String', 'AnsiString', 'WideString', 'UnicodeString', 'Utf8String',
  396. 'Single', 'Double' , 'Extended', 'Comp', 'Currency',
  397. 'TDateTime',
  398. '','', 'TStream', 'TStrings',
  399. '');
  400. Resourcestring
  401. SErrInvalidIdentifier = '"%s" is not a valid object pascal identifier.';
  402. SErrGeneratorExists = 'A code generator with name "%s" already exists';
  403. SUnknownGenerator = 'Unknown code generator name : "%s"';
  404. Function MakeIdentifier (S : String) : String;
  405. Function CreateString(S : String) : String;
  406. Procedure CheckIdentifier(AValue : String; AllowEmpty : Boolean = True);
  407. implementation
  408. Function CreateString(S : String) : String;
  409. begin
  410. Result:=StringReplace(S,'''','''''',[rfReplaceAll]);
  411. Result:=''''+Result+'''';
  412. end;
  413. Procedure CheckIdentifier(AValue : String; AllowEmpty : Boolean = True);
  414. begin
  415. If ((AValue='') and Not AllowEmpty) or Not IsValidIdent(AValue) then
  416. Raise ECodeGenerator.CreateFmt(SErrInvalidIdentifier,[AValue]);
  417. end;
  418. Var
  419. CodeGens : TCodeGenerators;
  420. function CodeGenerators: TCodeGenerators;
  421. begin
  422. If (CodeGens=Nil) then
  423. CodeGens:=TCodeGenerators.Create(TCodeGeneratorItem);
  424. Result:=CodeGens;
  425. end;
  426. Procedure DoneCodeGenerators;
  427. begin
  428. FreeAndNil(CodeGens);
  429. end;
  430. function RegisterCodeGenerator(const AName, ADescription: String;
  431. AClass: TDDCustomCodeGeneratorClass): TCodeGeneratorItem;
  432. begin
  433. CodeGenerators.RegisterCodeGenerator(AName,ADescription,AClass);
  434. end;
  435. procedure UnRegisterCodeGenerator(AClass: TDDCustomCodeGeneratorClass);
  436. begin
  437. CodeGenerators.UnRegisterCodeGenerator(AClass);
  438. end;
  439. procedure UnRegisterCodeGenerator(const AName: String);
  440. begin
  441. CodeGenerators.UnRegisterCodeGenerator(AName);
  442. end;
  443. Function MakeIdentifier (S : String) : String;
  444. Var
  445. I : Integer;
  446. begin
  447. Result:=S;
  448. For I:=Length(Result) downto 0 do
  449. If Not ((Upcase(Result[i]) in ['_','A'..'Z'])
  450. or ((I>0) and (Result[i] in (['0'..'9'])))) then
  451. Delete(Result,i,1);
  452. end;
  453. { TFieldPropDef }
  454. function TFieldPropDef.GetPropName: String;
  455. begin
  456. Result:=FPropName;
  457. If (Result='') then
  458. Result:=MakeIdentifier(FFieldName);
  459. end;
  460. function TFieldPropDef.GetPropType: TPropType;
  461. begin
  462. Result:=FPropType;
  463. If (Result=ptAuto) then
  464. Result:=FieldToPropTypeMap[FieldType];
  465. end;
  466. function TFieldPropDef.GetPropTypeStored: boolean;
  467. begin
  468. Result:=(FPropType<>ptAuto)
  469. end;
  470. procedure TFieldPropDef.SetFieldType(AValue: TFieldType);
  471. begin
  472. if FFieldType=AValue then Exit;
  473. FFieldType:=AValue;
  474. end;
  475. procedure TFieldPropDef.SetPropName(const AValue: String);
  476. begin
  477. If (AValue<>FPropName) then
  478. begin
  479. CheckIdentifier(AValue);
  480. FPropName:=AValue;
  481. end;
  482. end;
  483. procedure TFieldPropDef.InitFromField(F: TField);
  484. begin
  485. FieldType:=F.DataType;
  486. PropertySize:=F.Size;
  487. end;
  488. procedure TFieldPropDef.InitFromDDFieldDef(F: TDDFieldDef);
  489. begin
  490. FieldType:=F.FieldType;
  491. PropertySize:=F.Size;
  492. end;
  493. constructor TFieldPropDef.Create(ACollection: TCollection);
  494. begin
  495. inherited Create(ACollection);
  496. FPropVis:=vPublished
  497. end;
  498. procedure TFieldPropDef.Assign(ASource: TPersistent);
  499. Var
  500. PD : TFieldPropDef;
  501. begin
  502. if (ASource is TFieldPropDef) then
  503. begin
  504. PD:=ASource as TFieldPropDef;
  505. FEnabled:=PD.Enabled;
  506. FFieldName:=PD.FFieldName;
  507. FFieldType:=PD.FFIeldType;
  508. FPropAccess:=PD.FPropAccess;
  509. FPropDef:=PD.FPropDef;
  510. FPropType:=PD.FPropType;
  511. FPRopSize:=PD.FPropSize;
  512. FPropName:=PD.FPropName;
  513. FPropVis:=PD.FPropVis;
  514. end
  515. else
  516. inherited Assign(ASource);
  517. end;
  518. function TFieldPropDef.FieldPropDefs: TFieldPropDefs;
  519. begin
  520. Result:=Collection as TFieldPropDefs;
  521. end;
  522. function TFieldPropDef.HasGetter: Boolean;
  523. begin
  524. Result:=psRead in PropSetters;
  525. end;
  526. function TFieldPropDef.HasSetter: Boolean;
  527. begin
  528. Result:=(PropertyAccess in [paReadWrite,paWriteOnly])
  529. and ((PropertyType in [ptStream,ptTStrings]) or (psWrite in Propsetters));
  530. end;
  531. function TFieldPropDef.ObjPasTypeDef: String;
  532. begin
  533. If PropertyType in [ptCustom,ptSet,ptEnumerated] then
  534. Result:=PropertyDef
  535. else
  536. begin
  537. Result:=PropTypeNames[PropertyType];
  538. If PropertyType=ptShortString then
  539. Result:=Result+Format('String[%d]',[PropertySize]);
  540. end;
  541. end;
  542. function TFieldPropDef.ObjPasReadDef: String;
  543. begin
  544. If HasGetter then
  545. Result:='Get'+PropertyName
  546. else
  547. Result:='F'+PropertyName;
  548. end;
  549. function TFieldPropDef.ObjPasWriteDef: String;
  550. begin
  551. If HasSetter then
  552. Result:='Set'+PropertyName
  553. else
  554. Result:='F'+PropertyName;
  555. end;
  556. { TFieldPropDefs }
  557. function TFieldPropDefs.GetPropDef(Index : integer): TFieldPropDef;
  558. begin
  559. Result:=TFieldPropDef(Items[index]);
  560. end;
  561. procedure TFieldPropDefs.SetPropDef(Index : integer; const AValue: TFieldPropDef);
  562. begin
  563. Items[Index]:=AValue;
  564. end;
  565. function TFieldPropDefs.AddDef(AName: String): TFieldPropDef;
  566. begin
  567. Result:=Add As TFieldPropDef;
  568. Result.FieldName:=AName;
  569. end;
  570. procedure TFieldPropDefs.FromDataset(Dataset: TDataset; DoClear: Boolean = True);
  571. Var
  572. I : Integer;
  573. D : TFieldPropDef;
  574. F : TField;
  575. begin
  576. If DoClear then
  577. Clear;
  578. For I:=0 to Dataset.Fields.Count-1 do
  579. begin
  580. F:=Dataset.Fields[I];
  581. D:=AddDef(F.FieldName);
  582. D.Enabled:=True;
  583. D.InitFromField(F);
  584. end;
  585. end;
  586. procedure TFieldPropDefs.FromDDFieldDefs(Defs: TDDFieldDefs; DoClear: Boolean = True);
  587. Var
  588. I : Integer;
  589. D : TFieldPropDef;
  590. F : TDDFieldDef;
  591. begin
  592. If DoClear then
  593. Clear;
  594. For I:=0 to Defs.Count-1 do
  595. begin
  596. F:=Defs[I];
  597. D:=AddDef(F.FieldName);
  598. D.Enabled:=True;
  599. D.InitFromDDFieldDef(F);
  600. end;
  601. end;
  602. function TFieldPropDefs.IndexOfPropName(AName: String): Integer;
  603. begin
  604. Result:=Count-1;
  605. While (Result>=0) and (CompareText(GetPropDef(Result).PropertyName,AName)<>0) do
  606. Dec(Result);
  607. end;
  608. function TFieldPropDefs.IndexOfFieldName(AName: String): Integer;
  609. begin
  610. Result:=Count-1;
  611. While (Result>=0) and (CompareText(GetPropDef(Result).FieldName,AName)<>0) do
  612. Dec(Result);
  613. end;
  614. function TFieldPropDefs.FindPropName(AName: String): TFieldPropDef;
  615. Var
  616. I : Integer;
  617. begin
  618. I:=IndexOfPropName(AName);
  619. If (I<>-1) then
  620. Result:=GetpropDef(I)
  621. else
  622. Result:=Nil;
  623. end;
  624. function TFieldPropDefs.FindFieldName(AName: String): TFieldPropDef;
  625. Var
  626. I : Integer;
  627. begin
  628. I:=IndexOfFieldName(AName);
  629. If (I<>-1) then
  630. Result:=GetpropDef(I)
  631. else
  632. Result:=Nil;
  633. end;
  634. { TDDClassCodeGenerator }
  635. procedure TDDClassCodeGenerator.SetClassName(const AValue: String);
  636. begin
  637. end;
  638. procedure TDDClassCodeGenerator.SetAncestorClass(const AValue: String);
  639. begin
  640. FAncestorClass:=AValue;
  641. end;
  642. function TDDClassCodeGenerator.GetOpts: TClassCodeGeneratorOptions;
  643. begin
  644. Result:=CodeOptions as TClassCodeGeneratorOptions;
  645. end;
  646. procedure TDDClassCodeGenerator.SetFieldDefs(const AValue: TFieldPropDefs);
  647. begin
  648. if FFieldDefs=AValue then exit;
  649. FFieldDefs:=AValue;
  650. end;
  651. procedure TDDClassCodeGenerator.SetUnitname(const AValue: String);
  652. begin
  653. FUnitName:=AValue;
  654. end;
  655. function TDDClassCodeGenerator.CreateFieldPropDefs: TFieldPropDefs;
  656. begin
  657. Result:=TFieldPropDefs.Create(TFieldPropDef);
  658. end;
  659. constructor TDDClassCodeGenerator.Create(AOwner: TComponent);
  660. begin
  661. inherited Create(AOwner);
  662. FFieldDefs:=CreateFieldPropDefs;
  663. StringsClass:='TStringList';
  664. StreamClass:='TMemoryStream';
  665. end;
  666. destructor TDDClassCodeGenerator.Destroy;
  667. begin
  668. FreeAndNil(FFieldDefs);
  669. inherited Destroy;
  670. end;
  671. procedure TDDClassCodeGenerator.GenerateClass(Strings: TStrings);
  672. begin
  673. IncIndent;
  674. Try
  675. DoBeforeTypeSection(Strings);
  676. AddLn(Strings,'// Declaration');
  677. AddLn(Strings,'Type');
  678. AddLn(Strings);
  679. DoBeforeClassDeclaration(Strings);
  680. CreateDeclaration(Strings);
  681. DoAfterClassDeclaration(Strings);
  682. AddLn(Strings);
  683. DoAfterTypeSection(Strings);
  684. AddLn(Strings,'// Implementation');
  685. AddLn(Strings);
  686. DoBeforeClassImplementation(Strings);
  687. CreateImplementation(Strings);
  688. DoAfterClassImplementation(Strings);
  689. Finally
  690. DecIndent;
  691. end;
  692. end;
  693. function TDDClassCodeGenerator.AllowPropertyDeclaration(F: TFieldPropDef;
  694. AVisibility: TVisibilities): Boolean;
  695. begin
  696. Result:=Assigned(f) and F.Enabled and ((AVisibility=[]) or (F.PropertyVisibility in AVisibility));
  697. end;
  698. procedure TDDClassCodeGenerator.WritePropertyDeclaration(Strings: TStrings;
  699. F: TFieldPropDef);
  700. begin
  701. AddLn(Strings,PropertyDeclaration(Strings,F)+';');
  702. end;
  703. procedure TDDClassCodeGenerator.CreateDeclaration(Strings: TStrings);
  704. Const
  705. VisibilityNames : Array [TVisibility] of string
  706. = ('Private','Protected','Public','Published');
  707. Var
  708. V : TVisibility;
  709. I : Integer;
  710. F : TFieldPropDef;
  711. begin
  712. CreateClassHead(Strings);
  713. AddLn(Strings,VisibilityNames[vPrivate]);
  714. WritePrivateFields(Strings);
  715. For v:=Low(TVisibility) to High(TVisibility) do
  716. begin
  717. AddLn(Strings,VisibilityNames[v]);
  718. IncIndent;
  719. Try
  720. WriteVisibilityStart(V,Strings);
  721. For I:=0 to Fields.Count-1 do
  722. begin
  723. F:=Fields[i];
  724. if AllowPropertyDeclaration(F,[V]) then
  725. WritePropertyDeclaration(Strings,F);
  726. end;
  727. WriteVisibilityEnd(V,Strings);
  728. Finally
  729. Decindent;
  730. end;
  731. end;
  732. CreateClassEnd(Strings);
  733. end;
  734. procedure TDDClassCodeGenerator.WritePrivateFields(Strings: TStrings);
  735. Var
  736. I : Integer;
  737. F : TFieldPropDef;
  738. begin
  739. IncIndent;
  740. Try
  741. For I:=0 to Fields.Count-1 do
  742. begin
  743. F:=Fields[i];
  744. if AllowPropertyDeclaration(F,[]) then
  745. AddLn(Strings,'F%s : %s;',[F.PropertyName,F.ObjPasTypeDef]);
  746. end;
  747. Finally
  748. DecIndent;
  749. end;
  750. end;
  751. procedure TDDClassCodeGenerator.DoBeforeGetter(Strings: TStrings);
  752. begin
  753. end;
  754. procedure TDDClassCodeGenerator.CreateImplementation(Strings: TStrings);
  755. Var
  756. B : Boolean;
  757. I : Integer;
  758. F : TFieldPropDef;
  759. begin
  760. AddLn(Strings,' { %s } ',[ClassOptions.ObjectClassName]);
  761. AddLn(Strings);
  762. DoBeforeConstructor(Strings);
  763. If NeedsConstructor or NeedsDestructor then
  764. Addln(Strings,' { Constructor and destructor }');
  765. If NeedsConstructor then
  766. begin
  767. Addln(Strings);
  768. WriteConstructorImplementation(Strings);
  769. end;
  770. If NeedsDestructor then
  771. begin
  772. Addln(Strings);
  773. WriteDestructorImplementation(Strings);
  774. end;
  775. DoAfterDestructor(Strings);
  776. B:=False;
  777. For I:=0 to Fields.Count-1 do
  778. begin
  779. F:=Fields[i];
  780. if AllowPropertyDeclaration(F,[]) and F.HasGetter then
  781. begin
  782. If not B then
  783. begin
  784. B:=True;
  785. Addln(Strings,' { Property Getters }');
  786. Addln(Strings);
  787. end;
  788. WritePropertyGetterImpl(Strings,F);
  789. end;
  790. end;
  791. B:=False;
  792. For I:=0 to Fields.Count-1 do
  793. begin
  794. F:=Fields[i];
  795. if AllowPropertyDeclaration(F,[]) and F.HasSetter then
  796. begin
  797. If not B then
  798. begin
  799. B:=True;
  800. Addln(Strings,' { Property Setters }');
  801. Addln(Strings);
  802. end;
  803. WritePropertySetterImpl(Strings,F);
  804. end;
  805. end;
  806. end;
  807. procedure TDDClassCodeGenerator.WritePropertyGetterImpl(Strings: TStrings;
  808. F: TFieldPropDef);
  809. Var
  810. S : String;
  811. begin
  812. S:=PropertyGetterDeclaration(F,True);
  813. BeginMethod(Strings,S);
  814. AddLn(Strings,'begin');
  815. IncIndent;
  816. Try
  817. AddLn(Strings,Format('Result:=F%s;',[F.PropertyName]));
  818. Finally
  819. DecIndent;
  820. end;
  821. EndMethod(Strings,S);
  822. end;
  823. procedure TDDClassCodeGenerator.WritePropertySetterImpl(Strings: TStrings;
  824. F: TFieldPropDef);
  825. Var
  826. S : String;
  827. L : Integer;
  828. begin
  829. S:=PropertySetterDeclaration(F,True);
  830. BeginMethod(Strings,S);
  831. AddLn(Strings,'begin');
  832. IncIndent;
  833. Try
  834. AddLn(Strings,Format('if (F%s=AValue) then exit;',[F.PropertyName]));
  835. Case F.PropertyType of
  836. ptTStrings :
  837. S:=Format('F%s.Assign(AValue);',[F.PropertyName]);
  838. ptStream :
  839. S:=Format('F%s.CopyFrom(AValue,0);',[F.PropertyName]);
  840. else
  841. S:=Format('F%s:=AValue;',[F.PropertyName]);
  842. end;
  843. AddLn(Strings,S);
  844. S:=CodeOptions.ExtraSetterLine;
  845. L:=Length(S);
  846. if (L>0) then
  847. begin
  848. S:=StringReplace(S,'%PROPNAME%',F.PropertyName,[rfReplaceAll,rfIgnoreCase]);
  849. L:=Length(S);
  850. if (S[L]<>';') then
  851. S:=S+';';
  852. AddLn(Strings,S);
  853. end;
  854. Finally
  855. DecIndent;
  856. end;
  857. EndMethod(Strings,S);
  858. end;
  859. function TDDClassCodeGenerator.GetFieldDefs: TFieldPropDefs;
  860. begin
  861. Result:=FFieldDefs;
  862. end;
  863. function TDDClassCodeGenerator.CreateOptions: TCodeGeneratorOptions;
  864. begin
  865. Result:=TClassCodeGeneratorOptions.Create;
  866. end;
  867. procedure TDDClassCodeGenerator.DoBeforeTypeSection(Strings: TStrings);
  868. begin
  869. If Assigned(BeforeTypeSection) then
  870. BeforeTypeSection(Self,Strings);
  871. end;
  872. procedure TDDClassCodeGenerator.DoAfterTypeSection(Strings: TStrings);
  873. begin
  874. If Assigned(AfterTypeSection) then
  875. AfterTypeSection(Self,Strings);
  876. end;
  877. procedure TDDClassCodeGenerator.DoBeforeClassDeclaration(Strings: TStrings);
  878. begin
  879. if Assigned(BeforeClassDeclaration) then
  880. BeforeClassDeclaration(Self,Strings);
  881. end;
  882. procedure TDDClassCodeGenerator.DoAfterClassDeclaration(Strings: TStrings);
  883. begin
  884. if Assigned(AfterClassDeclaration) then
  885. AfterClassDeclaration(Self,Strings);
  886. end;
  887. procedure TDDClassCodeGenerator.DoBeforeConstructor(Strings: TStrings);
  888. begin
  889. If Assigned(BeforeConstructorImplementation) then
  890. BeforeConstructorImplementation(Self,Strings);
  891. end;
  892. procedure TDDClassCodeGenerator.DoAfterDestructor(Strings: TStrings);
  893. begin
  894. If Assigned(AfterDestructorImplementation) then
  895. AfterDestructorImplementation(Self,Strings);
  896. end;
  897. procedure TDDClassCodeGenerator.DoBeforeClassImplementation(Strings: TStrings);
  898. begin
  899. If Assigned(BeforeClassImplementation) then
  900. BeforeClassImplementation(Self,Strings);
  901. end;
  902. procedure TDDClassCodeGenerator.DoAfterClassImplementation(Strings: TStrings);
  903. begin
  904. If Assigned(AfterClassImplementation) then
  905. AfterClassImplementation(Self,Strings);
  906. end;
  907. procedure TDDClassCodeGenerator.DoGenerateInterface(Strings: TStrings);
  908. begin
  909. DoBeforeTypeSection(Strings);
  910. AddLn(Strings,'Type');
  911. AddLn(Strings);
  912. IncIndent;
  913. Try
  914. DoBeforeClassDeclaration(Strings);
  915. CreateDeclaration(Strings);
  916. DoAfterClassDeclaration(Strings);
  917. Finally
  918. DecIndent;
  919. end;
  920. DoAfterTypeSection(Strings);
  921. end;
  922. procedure TDDClassCodeGenerator.DoGenerateImplementation(Strings: TStrings);
  923. begin
  924. DoBeforeClassImplementation(Strings);
  925. CreateImplementation(Strings);
  926. DoAfterClassImplementation(Strings);
  927. end;
  928. function TDDClassCodeGenerator.GetClassInterfaces: String;
  929. begin
  930. Result:='';
  931. end;
  932. procedure TDDClassCodeGenerator.WriteConstructorImplementation(Strings: TStrings
  933. );
  934. Var
  935. I : Integer;
  936. F : TFieldPropDef;
  937. S : String;
  938. begin
  939. S:=ConstructorDeclaration(True);
  940. BeginMethod(Strings,S);
  941. AddLn(Strings,'begin');
  942. AddLn(Strings,' inherited;');
  943. IncIndent;
  944. Try
  945. For I:=0 to Fields.Count-1 do
  946. begin
  947. F:=Fields[i];
  948. if F.Enabled then
  949. WriteFieldCreate(Strings,F);
  950. end;
  951. Finally
  952. DecIndent;
  953. end;
  954. EndMethod(Strings,S);
  955. end;
  956. procedure TDDClassCodeGenerator.WriteDestructorImplementation(Strings: TStrings
  957. );
  958. Var
  959. I : Integer;
  960. F : TFieldPropDef;
  961. S : String;
  962. begin
  963. S:=DestructorDeclaration(True);
  964. BeginMethod(Strings,S);
  965. AddLn(Strings,'begin');
  966. IncIndent;
  967. Try
  968. For I:=0 to Fields.Count-1 do
  969. begin
  970. F:=Fields[i];
  971. if F.Enabled then
  972. WriteFieldDestroy(Strings,F);
  973. end;
  974. AddLn(Strings,'Inherited;');
  975. Finally
  976. DecIndent;
  977. end;
  978. EndMethod(Strings,S);
  979. end;
  980. procedure TDDClassCodeGenerator.WriteFieldCreate(Strings: TStrings;
  981. F: TFieldPropDef);
  982. Var
  983. S : String;
  984. begin
  985. Case F.PropertyType of
  986. ptTStrings :
  987. begin
  988. S:=Format('F%s:=%s.Create;',[F.PropertyName,StringsClass]);
  989. AddLn(Strings,S);
  990. end;
  991. ptStream :
  992. begin
  993. S:=Format('F%s:=%s.Create;',[F.PropertyName,StreamClass]);
  994. AddLn(Strings,S);
  995. end;
  996. ptCustom :
  997. begin
  998. AddLn(Strings,'// Add Creation for '+F.PropertyName);
  999. end;
  1000. end;
  1001. end;
  1002. procedure TDDClassCodeGenerator.WriteFieldDestroy(Strings: TStrings;
  1003. F: TFieldPropDef);
  1004. Var
  1005. S : String;
  1006. begin
  1007. Case F.PropertyType of
  1008. ptTStrings,
  1009. ptStream :
  1010. begin
  1011. S:=Format('FreeAndNil(F%s);',[F.PropertyName]);
  1012. AddLn(Strings,S);
  1013. end;
  1014. ptCustom :
  1015. begin
  1016. AddLn(Strings,'// Add destroy for '+F.PropertyName);
  1017. end;
  1018. end;
  1019. end;
  1020. procedure TDDClassCodeGenerator.CreateClassHead(Strings: TStrings);
  1021. Var
  1022. S : String;
  1023. begin
  1024. Addln(Strings,'{ %s }',[ClassOptions.ObjectClassName]);
  1025. AddLn(Strings);
  1026. S:=GetClassInterfaces;
  1027. if (S<>'') then
  1028. S:=','+S;
  1029. AddLn(Strings,'%s = Class(%s%s)',[ClassOptions.ObjectClassName,ClassOptions.AncestorClass,S])
  1030. end;
  1031. procedure TDDClassCodeGenerator.CreateClassEnd(Strings: TStrings);
  1032. begin
  1033. AddLn(Strings,'end;');
  1034. AddLn(Strings);
  1035. end;
  1036. procedure TDDClassCodeGenerator.WriteVisibilityStart(V: TVisibility;
  1037. Strings: TStrings);
  1038. Var
  1039. I : Integer;
  1040. F : TFieldPropDef;
  1041. begin
  1042. If (v=vPrivate) then
  1043. begin
  1044. For I:=0 to Fields.Count-1 do
  1045. begin
  1046. F:=Fields[i];
  1047. If AllowPropertyDeclaration(F,[]) then
  1048. begin
  1049. if (F.Hasgetter) then
  1050. AddLn(Strings,PropertyGetterDeclaration(F,False));
  1051. if (F.HasSetter) then
  1052. AddLn(Strings,PropertySetterDeclaration(F,False));
  1053. end;
  1054. end;
  1055. end
  1056. else if v=vPublic then
  1057. begin
  1058. If NeedsConstructor then
  1059. AddLn(Strings,ConstructorDeclaration(False));
  1060. If NeedsDestructor then
  1061. Addln(Strings,DestructorDeclaration(False));
  1062. end
  1063. // Do nothing
  1064. end;
  1065. procedure TDDClassCodeGenerator.WriteVisibilityEnd(V: TVisibility;
  1066. Strings: TStrings);
  1067. begin
  1068. // Do nothing
  1069. end;
  1070. function TDDClassCodeGenerator.PropertyDeclaration(Strings: TStrings;
  1071. Def: TFieldPropDef): String;
  1072. begin
  1073. Result:='Property '+Def.PropertyName+' ';
  1074. Result:=Result+': '+Def.ObjPasTypeDef;
  1075. If Def.PropertyAccess in [paReadWrite,paReadOnly] then
  1076. Result:=Result+' Read '+Def.ObjPasReadDef;
  1077. If Def.PropertyAccess in [paReadWrite,paWriteOnly] then
  1078. Result:=Result+' Write '+Def.ObjPasWriteDef;
  1079. end;
  1080. function TDDClassCodeGenerator.PropertyGetterDeclaration(Def: TFieldPropDef;
  1081. Impl: Boolean): String;
  1082. begin
  1083. Result:='Function ';
  1084. If Impl then
  1085. Result:=Result+Classoptions.ObjectClassName+'.';
  1086. Result:=Result+Def.ObjPasReadDef+' : '+Def.ObjPasTypeDef+';';
  1087. end;
  1088. function TDDClassCodeGenerator.PropertySetterDeclaration(Def: TFieldPropDef;
  1089. Impl: Boolean): String;
  1090. begin
  1091. Result:='Procedure ';
  1092. If Impl then
  1093. Result:=Result+ClassOptions.ObjectClassName+'.';
  1094. Result:=Result+Def.ObjPasWriteDef+' (AValue : '+Def.ObjPasTypeDef+');';
  1095. end;
  1096. function TDDClassCodeGenerator.NeedsConstructor: Boolean;
  1097. Var
  1098. I : Integer;
  1099. F : TFieldPropDef;
  1100. begin
  1101. Result:=False;
  1102. I:=Fields.Count-1;
  1103. While (Not Result) and (I>=0) do
  1104. begin
  1105. F:=Fields[i];
  1106. Result:=F.Enabled and (F.PropertyType in [ptStream,ptTStrings]);
  1107. Dec(I);
  1108. end;
  1109. end;
  1110. function TDDClassCodeGenerator.NeedsDestructor: Boolean;
  1111. begin
  1112. Result:=NeedsConstructor;
  1113. end;
  1114. function TDDClassCodeGenerator.ConstructorDeclaration(Impl: Boolean): String;
  1115. begin
  1116. Result:='Constructor ';
  1117. If Impl then
  1118. Result:=Result+ClassOptions.ObjectClassName+'.';
  1119. Result:=Result+'Create;';
  1120. end;
  1121. function TDDClassCodeGenerator.DestructorDeclaration(Impl: Boolean): String;
  1122. begin
  1123. Result:='Destructor ';
  1124. If Impl then
  1125. Result:=Result+ClassOptions.ObjectClassName+'.';
  1126. Result:=Result+'Destroy;';
  1127. if not Impl then
  1128. Result:=Result+' Override;';
  1129. end;
  1130. procedure TDDClassCodeGenerator.GenerateClass(Stream: TStream);
  1131. Var
  1132. L : TStringList;
  1133. begin
  1134. L:=TStringList.Create;
  1135. try
  1136. GenerateClass(L);
  1137. L.SaveToStream(Stream);
  1138. finally
  1139. L.Free;
  1140. end;
  1141. end;
  1142. { TDDCustomCodeGenerator }
  1143. procedure TDDCustomCodeGenerator.IncIndent;
  1144. begin
  1145. FCurrentIndent:=FCurrentIndent+StringOfChar(' ',FIndent);
  1146. end;
  1147. procedure TDDCustomCodeGenerator.DecIndent;
  1148. begin
  1149. Delete(FCurrentIndent,1,FIndent);
  1150. end;
  1151. procedure TDDCustomCodeGenerator.DoGenerateInterface(Strings: TStrings);
  1152. begin
  1153. end;
  1154. procedure TDDCustomCodeGenerator.DoGenerateImplementation(Strings: TStrings);
  1155. begin
  1156. end;
  1157. function TDDCustomCodeGenerator.GetFieldDefs: TFieldPropDefs;
  1158. begin
  1159. end;
  1160. procedure TDDCustomCodeGenerator.SetFieldDefs(const AValue: TFieldPropDefs);
  1161. begin
  1162. end;
  1163. function TDDCustomCodeGenerator.GetSQL: TStrings;
  1164. begin
  1165. Result:=Nil;
  1166. end;
  1167. procedure TDDCustomCodeGenerator.SetSQL(const AValue: TStrings);
  1168. begin
  1169. // Do nothing
  1170. end;
  1171. constructor TDDCustomCodeGenerator.Create(AOWner: TComponent);
  1172. begin
  1173. inherited Create(AOWner);
  1174. FCodeOptions:=CreateOptions;
  1175. FIndent:=2;
  1176. end;
  1177. destructor TDDCustomCodeGenerator.Destroy;
  1178. begin
  1179. FreeAndNil(FCodeOptions);
  1180. inherited Destroy;
  1181. end;
  1182. procedure TDDCustomCodeGenerator.AddLn(Strings : TStrings);
  1183. begin
  1184. Strings.Add('');
  1185. end;
  1186. procedure TDDCustomCodeGenerator.AddLn(Strings : TStrings; Line : String);
  1187. begin
  1188. Strings.Add(FCurrentIndent+Line);
  1189. end;
  1190. procedure TDDCustomCodeGenerator.AddLn(Strings: TStrings; Fmt: String;
  1191. Args: array of const);
  1192. begin
  1193. Strings.Add(FCurrentIndent+Format(Fmt,Args));
  1194. end;
  1195. function TDDCustomCodeGenerator.CreatePascalString(S: String; Quote: Boolean): String;
  1196. Var
  1197. SW : String;
  1198. begin
  1199. SW:=StringReplace(S,'''','''''',[rfReplaceAll]);
  1200. SW:=StringReplace(SW,#13#10,'''#13#10''',[rfReplaceAll]);
  1201. SW:=StringReplace(SW,#10,'''#10''',[rfReplaceAll]);
  1202. SW:=StringReplace(SW,#13,'''#13''',[rfReplaceAll]);
  1203. If Quote then
  1204. SW:=''''+SW+'''';
  1205. Result:=SW;
  1206. end;
  1207. function TDDCustomCodeGenerator.CreateOptions: TCodeGeneratorOptions;
  1208. begin
  1209. Result:=TCodeGeneratorOptions.Create;
  1210. end;
  1211. function TDDCustomCodeGenerator.GetInterfaceUsesClause: String;
  1212. begin
  1213. Result:='Classes, SysUtils';
  1214. If (CodeOptions.InterfaceUnits<>'') then
  1215. Result:=Result+','+CodeOptions.InterfaceUnits;
  1216. end;
  1217. function TDDCustomCodeGenerator.GetImplementationUsesClause: String;
  1218. begin
  1219. Result:=CodeOptions.ImplementationUnits;
  1220. end;
  1221. procedure TDDCustomCodeGenerator.GenerateCode(Stream: TStream);
  1222. Var
  1223. L : TStringList;
  1224. begin
  1225. L:=TStringList.Create;
  1226. try
  1227. GenerateCode(L);
  1228. L.SaveToStream(Stream);
  1229. finally
  1230. L.Free;
  1231. end;
  1232. end;
  1233. procedure TDDCustomCodeGenerator.GenerateCode(Strings: TStrings);
  1234. Procedure MaybeAddUsesClause(S : String);
  1235. begin
  1236. If (S<>'') then
  1237. begin
  1238. If S[Length(S)]<>';' then
  1239. S:=S+';';
  1240. AddLn(Strings,'Uses '+S);
  1241. AddLn(Strings);
  1242. end;
  1243. end;
  1244. Var
  1245. S : String;
  1246. begin
  1247. FCurrentIndent:='';
  1248. if (coUnit in CodeOptions.Options) then
  1249. begin
  1250. Addln(Strings,'Unit '+CodeOptions.UnitName+';');
  1251. Addln(Strings);
  1252. Addln(Strings, '{$mode objfpc}{$H+}');
  1253. Addln(Strings);
  1254. Addln(Strings,'Interface');
  1255. Addln(Strings);
  1256. S:=GetInterfaceUsesClause;
  1257. MaybeAddUsesClause(S);
  1258. end;
  1259. if coInterface in CodeOptions.Options then
  1260. begin
  1261. DoGenerateInterface(Strings);
  1262. Addln(Strings);
  1263. end;
  1264. FCurrentIndent:='';
  1265. if coUnit in CodeOptions.options then
  1266. begin
  1267. if coImplementation in CodeOptions.Options then
  1268. begin
  1269. Addln(Strings,'Implementation');
  1270. S:=GetImplementationUsesClause;
  1271. MaybeAddUsesClause(S);
  1272. end;
  1273. end;
  1274. if coImplementation in CodeOptions.Options then
  1275. begin
  1276. Addln(Strings);
  1277. DoGenerateImplementation(Strings);
  1278. end;
  1279. Addln(Strings);
  1280. if (coUnit in CodeOptions.options) then
  1281. Addln(Strings,'end.');
  1282. end;
  1283. class function TDDCustomCodeGenerator.NeedsSQL: Boolean;
  1284. begin
  1285. Result:=False;
  1286. end;
  1287. class function TDDCustomCodeGenerator.NeedsFieldDefs: Boolean;
  1288. begin
  1289. Result:=False;
  1290. end;
  1291. function TDDCustomCodeGenerator.ShowConfigDialog: Boolean;
  1292. begin
  1293. end;
  1294. procedure TDDCustomCodeGenerator.BeginMethod(STrings: TStrings;
  1295. const Decl: String);
  1296. begin
  1297. AddLn(Strings,Decl);
  1298. AddLn(Strings);
  1299. end;
  1300. procedure TDDCustomCodeGenerator.EndMethod(STrings: TStrings; const Decl: String
  1301. );
  1302. begin
  1303. AddLn(Strings,'end;');
  1304. Addln(Strings);
  1305. Addln(Strings);
  1306. end;
  1307. { TCodeGeneratorItem }
  1308. procedure TCodeGeneratorItem.SetName(const AValue: String);
  1309. Var
  1310. G : TCodeGeneratorItem;
  1311. begin
  1312. if (FName=AValue) then
  1313. exit;
  1314. If (AValue<>'') then
  1315. begin
  1316. G:=TCodeGenerators(Collection).FindCodeGenerator(AValue);
  1317. If (G<>Nil) and (G<>Self) then
  1318. Raise ECodeGenerator.CreateFmt(SErrGeneratorExists,[AValue]);
  1319. end;
  1320. FName:=AValue;
  1321. end;
  1322. { TCodeGenerators }
  1323. function TCodeGenerators.GetGen(Index: Integer): TCodeGeneratorItem;
  1324. begin
  1325. Result:=TCodeGeneratorItem(Items[Index]);
  1326. end;
  1327. procedure TCodeGenerators.SetGen(Index: Integer;
  1328. const AValue: TCodeGeneratorItem);
  1329. begin
  1330. Items[Index]:=AValue;
  1331. end;
  1332. function TCodeGenerators.RegisterCodeGenerator(const AName, ADescription : String;
  1333. AClass: TDDCustomCodeGeneratorClass): TCodeGeneratorItem;
  1334. begin
  1335. If (IndexOfCodeGenerator(AName)<>-1) then
  1336. Raise ECodeGenerator.CreateFmt(SErrGeneratorExists,[AName]);
  1337. Result:=Add as TCodeGeneratorItem;
  1338. Result.Name:=AName;
  1339. Result.Description:=ADescription;
  1340. Result.GeneratorClass:=AClass;
  1341. end;
  1342. procedure TCodeGenerators.UnRegisterCodeGenerator(AClass: TDDCustomCodeGeneratorClass);
  1343. begin
  1344. FindCodeGenerator(AClass).Free;
  1345. end;
  1346. procedure TCodeGenerators.UnRegisterCodeGenerator(const AName: String);
  1347. begin
  1348. FindCodeGenerator(AName).Free;
  1349. end;
  1350. function TCodeGenerators.IndexOfCodeGenerator(const AName: String): Integer;
  1351. begin
  1352. Result:=Count-1;
  1353. While (Result>=0) and (CompareText(GetGen(Result).Name,AName)<>0) do
  1354. Dec(Result);
  1355. end;
  1356. function TCodeGenerators.IndexOfCodeGenerator(AClass: TDDCustomCodeGeneratorClass): Integer;
  1357. begin
  1358. Result:=Count-1;
  1359. While (Result>=0) and (GetGen(Result).GeneratorClass<>AClass) do
  1360. Dec(Result);
  1361. end;
  1362. function TCodeGenerators.FindCodeGenerator(const AName: String): TCodeGeneratorItem;
  1363. Var
  1364. I : Integer;
  1365. begin
  1366. I:=IndexOfCodeGenerator(AName);
  1367. If (I=-1) then
  1368. Result:=Nil
  1369. else
  1370. Result:=GetGen(I);
  1371. end;
  1372. function TCodeGenerators.FindCodeGenerator(AClass: TDDCustomCodeGeneratorClass): TCodeGeneratorItem;
  1373. Var
  1374. I : Integer;
  1375. begin
  1376. I:=IndexOfCodeGenerator(AClass);
  1377. If (I=-1) then
  1378. Result:=Nil
  1379. else
  1380. Result:=GetGen(I);
  1381. end;
  1382. function TCodeGenerators.ConfigureCodeGenerator(
  1383. AGenerator: TDDCustomCodeGenerator): Boolean;
  1384. Var
  1385. G : TCodeGeneratorItem;
  1386. begin
  1387. Result:=True;
  1388. G:=FindCodeGenerator(TDDCustomCodeGeneratorClass(AGenerator.ClassType));
  1389. If Assigned(G) and Assigned(G.OnConfigureDialog) then
  1390. Result:=G.OnConfigureDialog(AGenerator);
  1391. end;
  1392. function TCodeGenerators.GeneratorByName(const AName: String): TCodeGeneratorItem;
  1393. begin
  1394. Result:=FindCodeGenerator(AName);
  1395. If (Result=Nil) then
  1396. Raise ECodegenerator.CreateFmt(SUnknownGenerator,[AName]);
  1397. end;
  1398. { TCodeGeneratorOptions }
  1399. procedure TCodeGeneratorOptions.SetOPtions(const AValue: TCodeOptions);
  1400. begin
  1401. FOptions:=AValue;
  1402. end;
  1403. constructor TCodeGeneratorOptions.create;
  1404. begin
  1405. FOptions:=[coInterface,coImplementation,coUnit];
  1406. UnitName:='Unit1';
  1407. end;
  1408. procedure TCodeGeneratorOptions.Assign(ASource: TPersistent);
  1409. Var
  1410. CG : TCodeGeneratorOptions;
  1411. begin
  1412. If ASource is TCodeGeneratorOptions then
  1413. begin
  1414. CG:=ASource as TCodeGeneratorOptions;
  1415. FInterfaceUnits:=CG.InterfaceUnits;
  1416. FImplementationUnits:=CG.ImplementationUnits;
  1417. FOptions:=CG.FOptions;
  1418. FUnitName:=CG.UnitName;
  1419. FExtraSetterLine:=CG.ExtraSetterLine;
  1420. end
  1421. else
  1422. inherited Assign(ASource);
  1423. end;
  1424. procedure TCodeGeneratorOptions.SetUnitname(const AValue: String);
  1425. begin
  1426. if FUnitName=AValue then exit;
  1427. CheckIdentifier(AValue,False);
  1428. FUnitName:=AValue;
  1429. end;
  1430. procedure TCodeGeneratorOptions.SetInterfaceUnits(const AValue: String);
  1431. begin
  1432. if FInterfaceUnits=AValue then exit;
  1433. FInterfaceUnits:=AValue;
  1434. // Do some checks here
  1435. end;
  1436. procedure TCodeGeneratorOptions.SetImplementationUnits(const AValue: String);
  1437. begin
  1438. if FImplementationUnits=AValue then exit;
  1439. FImplementationUnits:=AValue;
  1440. end;
  1441. { TClassCodeGeneratorOptions }
  1442. procedure TClassCodeGeneratorOptions.SetClassName(const AValue: String);
  1443. begin
  1444. if FClassName=AValue then
  1445. exit;
  1446. CheckIdentifier(AValue,False);
  1447. FClassName:=AValue;
  1448. end;
  1449. procedure TClassCodeGeneratorOptions.Assign(ASource: TPersistent);
  1450. Var
  1451. CO : TClassCodeGeneratorOptions;
  1452. begin
  1453. If ASource is TClassCodeGeneratorOptions then
  1454. begin
  1455. CO:=ASource as TClassCodeGeneratorOptions;
  1456. FClassName:=CO.FClassName;
  1457. FAncestorClass:=CO.FAncestorClass;
  1458. end;
  1459. inherited Assign(ASource);
  1460. end;
  1461. function TClassCodeGeneratorOptions.CleanObjectClassName: String;
  1462. Var
  1463. S : String;
  1464. begin
  1465. S:=ObjectClassName;
  1466. if (Length(S)>1) and (S[1]='T') then
  1467. Delete(S,1,1);
  1468. Result:=S;
  1469. end;
  1470. procedure TClassCodeGeneratorOptions.SetAncestorClass(const AValue: String);
  1471. begin
  1472. if (FAncestorClass=AValue) then
  1473. Exit;
  1474. CheckIdentifier(AValue,False);
  1475. FAncestorClass:=AValue;
  1476. end;
  1477. Finalization
  1478. DoneCodeGenerators;
  1479. end.