tstopas.pp 97 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419
  1. {
  2. This file is part of the Free Component Library
  3. Typedescript declarations to pascal code converter
  4. Copyright (c) 2021 by Michael Van Canneyt [email protected]
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit tstopas;
  12. {$mode objfpc}{$H+}
  13. interface
  14. uses
  15. Classes, SysUtils, contnrs, jsbase, jstree, jsscanner, jsparser,pascodegen;
  16. Type
  17. ETSToPas = Class(Exception);
  18. TJSFuncDefArray = Array of TJSFuncDef;
  19. { TPasData }
  20. TPasData = Class(TObject)
  21. private
  22. FOriginalName: TJSString;
  23. FPasName: String;
  24. Public
  25. Constructor Create(const aOriginalName : jsBase.TJSString; const APasName : String);
  26. Destructor destroy; override;
  27. Property PasName : String read FPasName;
  28. Property OriginalName : TJSString Read FOriginalName;
  29. end;
  30. TConversionOption = (coRaw,coGenericArrays,coUseNativeTypeAliases,coLocalArgumentTypes, coUntypedTuples, coDynamicTuples,
  31. coExternalConst,coExpandUnionTypeArgs,coaddOptionsToheader,coInterfaceAsClass,coSkipImportStatements);
  32. TConversionOptions = Set of TConversionOption;
  33. TTypescriptToPas = Class;
  34. TScope = Record
  35. Source : TJSSourceElements;
  36. Forwards : TStringList;
  37. end;
  38. { TTSContext }
  39. TTSContext = class(TObject)
  40. Private
  41. FCurrentScopeIdx: Integer;
  42. FTypeMap : TFPObjectHashTable;
  43. FTypeDeclarations : TFPObjectList;
  44. FConverter : TTypescriptToPas;
  45. FScopes : Array of TScope;
  46. function GetCurrentForwards: TStringList;
  47. function GetCurrentScope: TJSSourceElements;
  48. Protected
  49. procedure TypesToMap; virtual;
  50. Public
  51. Constructor Create(aConverter : TTypescriptToPas);
  52. Destructor Destroy; override;
  53. procedure DoGlobalFree(aEl: TJSElement);
  54. Procedure AddAliases(aAliases : TStrings);
  55. Procedure PushScope(aScope : TJSSourceElements; aForwards : TStringList);
  56. Procedure PopScope(aScope : TJSSourceElements; aForwards : TStringList);
  57. function ResolveTypeRef(D: TJSTypeDef): TJSTypeDef;
  58. function GetTypeName(const aTypeName: jsBase.TJSString; ForTypeDef: Boolean; UsePascal : Boolean): String;
  59. Function FindInNodes(aNodes: TJSElementNodes; const aName: String): TJSTypeDeclaration;
  60. Function FindInScope(aScope: TJSSourceElements; const aName: String): TJSTypeDef;
  61. Function FindTypeDef(const aName : String) : TJSTypeDef;
  62. Function FindTypeAlias(const aName : jsbase.TJSString) : String;
  63. Procedure AddToTypeMap(const aName : UTF8String; const aPasName : String);
  64. Procedure AddToTypeMap(const aName : jsbase.TJSString; const aPasName : String);
  65. Procedure AddToTypeMap(aType : TJSElement);
  66. Procedure RemoveFromTypeMap(aType : TJSElement);
  67. Property TypeMap : TFPObjectHashTable Read FTypeMap;
  68. Property CurrentScopeIdx : Integer Read FCurrentScopeIdx;
  69. Property CurrentScope : TJSSourceElements Read GetCurrentScope;
  70. Property CurrentForwards : TStringList Read GetCurrentForwards;
  71. end;
  72. { TTSJSScanner }
  73. TTSJSScanner = class(TJSScanner)
  74. private
  75. FContext: TTSContext;
  76. Public
  77. Property Context : TTSContext Read FContext Write FContext;
  78. end;
  79. { TTSJSParser }
  80. TTSJSParser = class(TJSParser)
  81. private
  82. FContext: TTSContext;
  83. Protected
  84. Procedure FreeElement(aElement : TJSElement); override;
  85. Function CreateElement(AElementClass : TJSElementClass) : TJSElement; override;
  86. Public
  87. Property Context : TTSContext Read FContext Write FContext;
  88. end;
  89. // List of TJSTypedParams
  90. { TFunctionOverLoadArgumentsList }
  91. TFunctionOverLoadArgumentsList = Class(TFPObjectList)
  92. Procedure AddOverload(aTypedParams : TJSTypedParams);
  93. Procedure RemoveDuplicates(aContext : TTSContext);
  94. end;
  95. { TTypescriptToPas }
  96. TTypescriptToPas = Class(TPascalCodeGenerator)
  97. private
  98. FClassPrefix: String;
  99. FClassSuffix: String;
  100. FContext: TTSContext;
  101. FDefaultClassParent: String;
  102. FDictionaryClassParent: String;
  103. FElements: TJSFunctionBody;
  104. FFieldPrefix: String;
  105. FIncludeImplementationCode: TStrings;
  106. FIncludeInterfaceCode: TStrings;
  107. FInputFileName: String;
  108. FInputStream: TStream;
  109. FLinkStatements: TStrings;
  110. FOptions: TConversionOptions;
  111. FOutputFileName: String;
  112. FTypeAliases: TStrings;
  113. FVerbose: Boolean;
  114. FECMAVersion: TECMAVersion;
  115. FPasNameList : TFPObjectList;
  116. FScopeNameList : Array[0..16] of TFPStringHashTable;
  117. FScopeIdx : Integer;
  118. FCurrentNameSpace : String;
  119. FForwards : TStrings;
  120. procedure CheckUnitName(SourceElements: TJSSourceElements);
  121. procedure DumpElements;
  122. function GetAccessName(aAccess: TAccessibility): string;
  123. function GetFixedValueTypeName(ATypeDef: TJSFixedValueReference): String;
  124. function GetIsRaw: Boolean;
  125. function HasReadOnlyPropFields(aTypeDef: TJSObjectTypeDef): Boolean;
  126. function HaveClass(const aName: TJSString): Boolean;
  127. function HaveModule(const aName: TJSString): Boolean;
  128. function NamespaceExtendsClass(aNs: TJSNamespaceDeclaration): Boolean;
  129. function NamespaceExtendsModule(aNs: TJSNamespaceDeclaration): Boolean;
  130. function ResolveTypeRef(D: TJSTypeDef): TJSTypeDef;
  131. procedure SetFLinkStatements(AValue: TStrings);
  132. procedure SetIncludeImplementationCode(AValue: TStrings);
  133. procedure SetIncludeInterfaceCode(AValue: TStrings);
  134. procedure SetTypeAliases(AValue: TStrings);
  135. Protected
  136. function GetGenericParams(aTypeParams: TJSElementNodes): String; virtual;
  137. procedure AddOptionsToHeader;
  138. Procedure PushNameScope;
  139. Procedure PopNameScope;
  140. function NameScopeHas(const aName : string) : Boolean;
  141. procedure AddToNameScope(const aName : String; aData : jsbase.TJSString);
  142. Procedure Parse; virtual;
  143. Procedure WritePascal; virtual;
  144. Function NeedsTypeMap(El : TJSElement) : Boolean;
  145. function CreateParser(aContext: TTSContext; S: TJSScanner): TJSParser; virtual;
  146. function CreateScanner(aContext : TTSContext; S: TStream): TJSScanner;virtual;
  147. Function CreateContext : TTSContext; virtual;
  148. Function BaseUnits : String; override;
  149. procedure WriteLinkStatements(aList: TStrings);
  150. // Auxiliary routines
  151. procedure Getoptions(L: TStrings); virtual;
  152. procedure ProcessDefinitions; virtual;
  153. Function ExportNode(aNode : TJSElementNode) : Boolean;
  154. function CheckUnionTypeDefinition(D: TJSTypeDef): TJSUnionTypeDef;
  155. function CreatePasName(const aOriginal : jsBase.TJSString; const aName: String): TPasData;virtual;
  156. function TypeNeedsTypeName(aType: TJSElement; IgnoreData : Boolean; IsResultType : Boolean = False): Boolean;
  157. procedure AllocatePasNames(FD: TJSFuncDef; aPrefix: String='');
  158. procedure AllocatePasNames(aList: TJSSourceElements; ParentName: String=''); virtual;
  159. procedure AllocatePasNames(aList: TJSElementNodes; ParentName: String=''); virtual;
  160. Function AllocatePasName(D: TJSElement; ParentName: String='') : TPasData;virtual;
  161. procedure EnsureUniqueNames(ML: TJSSourceElements);virtual;
  162. function GetExternalMemberName(const aName: jsBase.TJSString): string;
  163. function GetName(ADef: TJSElement): String;virtual;
  164. function GetName(ADef: TJSTypedParam): String;virtual;
  165. function GetName(ADef: TJSFuncDef): String;virtual;
  166. function HaveConsts(aList: TJSSourceElements): Boolean;virtual;
  167. function GetTypeName(Const aTypeName: JSBase.TJSString; ForTypeDef: Boolean=False): String;virtual;
  168. function GetTypeName(aTypeDef: TJSTypeDef; ForTypeDef: Boolean=False): String;virtual;
  169. // Functions
  170. // Overload handling
  171. function GetOverloads(const aDefs: TJSFuncDefArray): TFunctionOverLoadArgumentsList;
  172. procedure AddOverloadParams(aList: TFunctionOverLoadArgumentsList; adef: TJSFuncDef; aIdx: Integer);
  173. procedure AddUnionOverloads(aList: TFunctionOverLoadArgumentsList; const AName: TJSString; UT: TJSUnionTypeDef);
  174. procedure AddParameterToOverloads(aList: TFunctionOverLoadArgumentsList; const AName: TJSString; ATypeDef: TJSTypeDef);
  175. procedure AddParameterToOverloads(aList: TFunctionOverLoadArgumentsList; const aParam : TJSTypedParam);
  176. function CloneNonPartialParameterList(aList: TFunctionOverLoadArgumentsList; ADest: TFunctionOverLoadArgumentsList = Nil; AsPartial: Boolean = True): integer;
  177. function GetArguments(aList: TJSTypedParams; ForceBrackets: Boolean): String;
  178. function WriteFunctionDefinition(const aName: String; const aDefs: TJSFuncDefArray; UseExternal : Boolean): Boolean;
  179. function WriteFunctionDefs(aElements : TJSElementNodes; UseExternal : Boolean) : Integer;
  180. // Classes
  181. // Actual definitions. Return true if a definition was written.
  182. function WritePrivateReadOnlyField(P: TJSPropertyDeclaration): Boolean;
  183. function WritePrivateReadOnlyField(M: TJSMethodDeclaration): Boolean;
  184. function WriteReadonlyProperty(aProp: TJSPropertyDeclaration): Boolean;
  185. function WritePropertyDef(aProp: TJSPropertyDeclaration): Boolean;
  186. function WriteReadOnlyPropFields(aTypeDef: TJSObjectTypeDef): Integer;
  187. function WriteAmbientClassDef(const aPasName: String; aOrgName: TJSString; aTypeParams: TJSElementNodes; aClass: TJSAmbientClassDeclarationArray): Boolean;
  188. function WriteClassDefs(aClasses: TJSElementNodes) : Integer;
  189. // Forwards
  190. function WriteForwardClass(aName: string): Boolean;
  191. function WriteForwardClassDef(aIntf: TJSInterfaceDeclaration): Boolean;
  192. function WriteForwardClassDef(aObj: TJSTypeDeclaration): Boolean;
  193. function WriteForwardClassDef(aClass: TJSClassDeclaration): Boolean;
  194. function WriteForwardClassDef(aModule: TJSModuleDeclaration): Boolean;
  195. function WriteForwardClassDef(aNamespace: TJSNameSpaceDeclaration): Boolean;
  196. function WriteForwardClassDefs(aClassList: TJSElementNodes): Integer;
  197. Function WriteNamespaceDef(aNameSpace: TJSNamespaceDeclaration): Boolean;
  198. Function WriteNamespaceDefs(aNameSpaces: TJSElementNodes): Integer;
  199. Function WriteModuleDef(aModule: TJSModuleDeclaration): Boolean;
  200. Function WriteModuleDefs(aModules: TJSElementNodes): Integer;
  201. // Interfaces
  202. function WriteInterfaceDef(Intfs: TJSInterfaceDeclarationArray): Boolean;
  203. function WriteInterfaceDefs(aList: TJSElementNodes): Integer;
  204. // Properties
  205. procedure WritePropertyDeclaration(D: TJSVariableStatement);
  206. function WriteProperties(aClass: TJSClassDeclaration): Integer;
  207. function WriteProperties(aAccess : TAccessibility; aMembers: TJSElementNodes): Integer;
  208. function WriteObjectMethods(aAccess: TAccessibility; aTypeDef: TJSObjectTypeDef): Integer;
  209. procedure WriteIndexSignature(aSign: TJSIndexSignatureDeclaration);
  210. // Variables
  211. procedure WriteVariable(aVar: TJSVarDeclaration);
  212. procedure WriteVariables(Vars: TJSElementNodes); virtual;
  213. // Get type defs as string
  214. function GetTypeAsString(aType: TJSTypeDef; asPascal, asSubType: Boolean): String;
  215. function GetArrayTypeAsString(aTypeDef: TJSArrayTypeDef; asPascal, asSubType: Boolean): String;
  216. function GetAliasTypeAsString(aTypeDef: TJSTypeReference; asPascal, asSubType: Boolean): string;
  217. function GetIntersectionTypeAsString(aTypeDef: TJSIntersectionTypeDef; asPascal, asSubType: Boolean): String;
  218. function GetUnionTypeAsString(aTypeDef: TJSUnionTypeDef; asPascal, asSubType: Boolean): String;
  219. function GetEnumTypeAsString(aTypeDef: TJSEnumTypeDef; asPascal, asSubType: Boolean): String;
  220. function GetFixedValueTypeAsString(aTypeDef : TJSFixedValueReference; asPascal,asSubType : Boolean) : string;
  221. function GetTupleTypeAsString(aTypeDef: TJSTupleTypeDef; asPascal, asSubType: Boolean): String;
  222. // Write types
  223. procedure WriteTypeDefs(Types: TJSElementNodes); virtual;
  224. procedure WriteObjectTypeMembers(const aPasName: String; const aOrigName: jsBase.TJSString; aTypeParams: TJSElementNodes; aTypeDef: TJSObjectTypeDef);
  225. procedure WriteObjectTypedef(const aPasName: String; const aOrigName : jsBase.TJSString; aTypeParams: TJSElementNodes; aTypeDef: TJSObjectTypeDef); virtual;
  226. procedure WriteAliasTypeDef(const aPasName: string; const aOrgName: jsBase.TJSString; aTypeParams: TJSElementNodes; aTypeDef: TJSTypeReference); virtual;
  227. procedure WriteUnionTypeDef(const aPasName: string; const aOrgName: jsBase.TJSString; aTypeParams: TJSElementNodes; aTypeDef: TJSUnionTypeDef); virtual;
  228. procedure WriteTupleTypeDef(const aPasName: string; const aOrgName: jsBase.TJSString; aTypeParams: TJSElementNodes; aTypeDef: TJSTupleTypeDef); virtual;
  229. procedure WriteIntersectionTypeDef(const aPasName: string; const aOrgName: jsBase.TJSString; aTypeParams: TJSElementNodes; aTypeDef: TJSIntersectionTypeDef); virtual;
  230. procedure WriteArrayTypeDef(const aPasName: string; const aOrgName: jsBase.TJSString; aTypeParams: TJSElementNodes; aTypeDef: TJSArrayTypeDef); virtual;
  231. procedure WriteEnumTypeDef(const aPasName: string; const aOrgName: jsBase.TJSString; aTypeParams: TJSElementNodes; aTypeDef: TJSEnumTypeDef); virtual;
  232. function WriteFunctionTypeDef(const aPasName: string; const aOrgName: jsBase.TJSString; aTypeParams: TJSElementNodes; aDef: TJSFuncDef): Boolean; virtual;
  233. procedure WriteTypeDef(const aPasName: string; const aOrgName: jsBase.TJSString; aTypeParams: TJSElementNodes; aTypeDef: TJSTypeDef); virtual;
  234. // Indirect type handling
  235. Function HasIndirectTypeDefs(aParams: TJStypedParams): Boolean;
  236. Function HasIndirectTypeDefs(aElements: TJSElementNodes): Boolean;
  237. function AllocateIndirectTypeDef(El: TJSElement; const aPrefix, aName: String): Integer;
  238. Function AllocateIndirectTypeDefs(aElements : TJSElementNodes; const aPrefix : String) : Integer;
  239. function AllocateIndirectTypeDefs(FD: TJSFuncDef; const aPrefix: String): Integer;
  240. Function AllocateIndirectTypeDefs(aParams : TJSTypedParams; const aPrefix : String) : Integer;
  241. function AllocateTypeName(aType: TJSElement; const aPrefix, aName: String): Integer;
  242. function WriteIndirectTypeDefs(aEl: TJSElement): Integer;
  243. function WriteIndirectTypeDefs(FD: TJSFuncDef): Integer;
  244. function WriteIndirectTypeDefs(aParams: TJStypedParams): Integer; overload; virtual;
  245. Function WriteIndirectTypeDefs(aElements : TJSElementNodes) : Integer; overload; virtual;
  246. function WriteClassIndirectTypeDefs(aElements: TJSElementNodes; isClassLocal: Boolean): Integer;
  247. function WritePropertyTypeDefs(aElements: TJSElementNodes; Const SectionName: String=''): Integer;
  248. function WriteMethodParameterDefs(aElements: TJSElementNodes; Const SectionName : String = ''): Integer;
  249. // List of identifiers: global, namespace or class
  250. procedure WriteSourceElements(SourceElements: TJSSourceElements; aNamespace: TJSString);
  251. // Extra interface/Implementation code.
  252. procedure WriteImports(SourceElements: TJSSourceElements);
  253. procedure WriteImplementation; virtual;
  254. procedure WriteIncludeInterfaceCode; virtual;
  255. Property Elements : TJSFunctionBody Read FElements;
  256. Property Context : TTSContext Read FContext;
  257. Property IsRaw : Boolean Read GetIsRaw;
  258. Public
  259. Constructor Create(Aowner : TComponent); override;
  260. Destructor Destroy; override;
  261. Procedure Execute;
  262. Property InputStream : TStream Read FInputStream Write FInputStream;
  263. Published
  264. Property InputFileName : String Read FInputFileName Write FInputFileName;
  265. Property OutputFileName : String Read FOutputFileName Write FOutputFileName;
  266. Property Verbose : Boolean Read FVerbose Write FVerbose;
  267. Property FieldPrefix : String Read FFieldPrefix Write FFieldPrefix;
  268. Property ClassPrefix : String Read FClassPrefix Write FClassPrefix;
  269. Property ClassSuffix : String Read FClassSuffix Write FClassSuffix;
  270. Property Options : TConversionOptions Read FOptions Write FOptions;
  271. Property ECMAVersion : TECMAVersion Read FECMAVersion Write FECMAVersion;
  272. Property TypeAliases : TStrings Read FTypeAliases Write SetTypeAliases;
  273. Property IncludeInterfaceCode : TStrings Read FIncludeInterfaceCode Write SetIncludeInterfaceCode;
  274. Property IncludeImplementationCode : TStrings Read FIncludeImplementationCode Write SetIncludeImplementationCode;
  275. Property DictionaryClassParent : String Read FDictionaryClassParent Write FDictionaryClassParent;
  276. Property DefaultClassParent : String Read FDefaultClassParent Write FDefaultClassParent;
  277. Property LinkStatements : TStrings Read FLinkStatements Write SetFLinkStatements;
  278. end;
  279. implementation
  280. uses typinfo, strutils;
  281. Resourcestring
  282. SErrorCannotPopNilScope = 'Cannot pop nil scope';
  283. SErrCannotPushNilScope = 'Cannot push nil scope';
  284. SErrCanOnlyPopToplevelScope = 'Can only pop toplevel scope/forwards';
  285. SErrIgnoringDuplicateTypeName = 'Ignoring duplicate type name %s -> %s (%s)';
  286. SErrParseResultIsNotFunctionBody = 'Parse result is not a function body';
  287. SErrCannotGetTypeNameFromType = 'Cannot get type name from %s at row %d, col %d.';
  288. SErrUnsupportedNamedParamType = 'Unsupported named type parameter: "%s"';
  289. ResUnsupportedTypeParameter = 'Unsupported type parameter: "%s"';
  290. SCommentImportFile = 'Import file : %s';
  291. SCommentRequiredImportFile = 'Import (require) file : ';
  292. SLogRenamedType = 'Renamed %s to %s';
  293. SLogRenamingUnitCompile = 'Renaming unit %s to %s to allow compilation.';
  294. SErrRenamingUnitConflict = 'Renaming unit %s to %s to avoid name conflict.';
  295. SLogParsedNDefinitions = 'Parsed %d type definitions.';
  296. SErrUnsupportedTupleElementType = 'Unsupported tuple element type: %s';
  297. SCommentIgnoringDuplicateType = 'Ignoring duplicate type %s (%s)';
  298. SErrUnsupportedType = '%s (%s) has unsupported type "%s" : ';
  299. SErrNoNameAllocatedForFunctionResult = 'No name allocated for function %s (%d,%d) result type %s';
  300. SErrElementWithoutTypeName = 'Element without allocated typename: %s %s';
  301. SLogFoldingClassDefinitions = 'Folding %d definitions to 1 class for %s';
  302. SLogIgnoringEmptyMethod = 'Ignoring empty method';
  303. SLogIgnoringEmptyFunction = 'Ignoring empty function definition';
  304. SLogIgnoreDoubleClassDefinition = 'Ignore double class definition: "%s"';
  305. SForwardClassDefinitions = 'Forward class definitions';
  306. SLogFoldingInterfaceDefinitions = 'Folding %d definitions to 1 interface for %s';
  307. { TFunctionOverLoadArgumentsList }
  308. procedure TFunctionOverLoadArgumentsList.AddOverload(aTypedParams: TJSTypedParams);
  309. begin
  310. Add(aTypedParams);
  311. end;
  312. procedure TFunctionOverLoadArgumentsList.RemoveDuplicates(aContext: TTSContext);
  313. Function GetName(aDef : TJSTypeDef) : TJSString;
  314. begin
  315. Result:='';
  316. if aDef is TJSFixedValueReference then
  317. begin
  318. Case TJSFixedValueReference(aDef).FixedValue.Value.ValueType of
  319. jstString : Result:='string';
  320. jstNumber : Result:='number';
  321. jstBoolean : Result:='boolean';
  322. else
  323. Result:='';
  324. end
  325. end
  326. else if aDef is TJSTypeReference then
  327. Result:=(aDef as TJSTypeReference).Name
  328. else if aDef is TJSUnionOrIntersectTypeDef then
  329. Result:='jsvalue';
  330. end;
  331. Function IdenticalTypes(Src,Dest : TJSTypeDef) : boolean;
  332. Var
  333. N1,N2 : TJSString;
  334. begin
  335. Result:=Src=Dest;
  336. If Result then exit;
  337. Src:=aContext.ResolveTypeRef(Src);
  338. Dest:=aContext.ResolveTypeRef(Dest);
  339. Result:=Src=Dest;
  340. if Result then
  341. exit;
  342. N1:=GetName(Src);
  343. N2:=GetName(Dest);
  344. Result:=(N1=N2) and (N1<>'')
  345. end;
  346. Function IdenticalParams(Src,Dest : TJSTypedParams) : boolean;
  347. Var
  348. I : Integer;
  349. begin
  350. Result:=(Src.Count=Dest.Count);
  351. I:=Src.Count-1;
  352. While Result and (I>=0) do
  353. begin
  354. Result:=IdenticalTypes(Src.Types[i] as TJSTypeDef,Dest.Types[i] as TJSTypeDef);
  355. Dec(I);
  356. end;
  357. end;
  358. Function HasDuplicate(MaxIndex : Integer; aParamList :TJSTypedParams) : Boolean;
  359. Var
  360. I : Integer;
  361. begin
  362. Result:=False;
  363. I:=MaxIndex;
  364. While (Not Result) and (I>=0) do
  365. begin
  366. Result:=IdenticalParams(Items[i] as TJSTypedParams, aParamList);
  367. Dec(I);
  368. end
  369. end;
  370. Var
  371. I : Integer;
  372. begin
  373. For I:=Count-1 downto 1 do
  374. If HasDuplicate(I-1,Items[I] as TJSTypedParams) then
  375. Delete(I);
  376. end;
  377. { TTSJSParser }
  378. Procedure TTSJSParser.FreeElement(aElement : TJSElement);
  379. begin
  380. if Assigned(aElement) then
  381. FContext.RemoveFromTypeMap(aElement);
  382. Inherited;
  383. end;
  384. function TTSJSParser.CreateElement(AElementClass: TJSElementClass): TJSElement;
  385. begin
  386. Result:=inherited CreateElement(AElementClass);
  387. If Result is TJSTypeDeclaration then
  388. FContext.AddToTypeMap(Result)
  389. else If Result is TJSObjectTypeDef then
  390. FContext.AddToTypeMap(Result)
  391. else If (Result is TJSClassDeclaration) then
  392. FContext.AddToTypeMap(Result);
  393. end;
  394. { TTSContext }
  395. constructor TTSContext.Create(aConverter : TTypescriptToPas);
  396. begin
  397. TJSElement.GlobalFreeHook:=@DoGlobalFree;
  398. FCurrentScopeIdx:=-1;
  399. FConverter:=aConverter;
  400. FTypeMap:=TFPObjectHashTable.Create(False);
  401. FTypeDeclarations:=TFPObjectList.Create(False);
  402. SetLength(FScopes,10);
  403. end;
  404. destructor TTSContext.Destroy;
  405. begin
  406. TJSElement.GlobalFreeHook:=Nil;
  407. FreeAndNil(FTypeDeclarations);
  408. FreeAndNil(FTypeMap);
  409. inherited Destroy;
  410. end;
  411. procedure TTSContext.AddAliases(aAliases: TStrings);
  412. Var
  413. I : Integer;
  414. N,V : String;
  415. begin
  416. For I:=0 to aAliases.Count-1 do
  417. begin
  418. aAliases.GetNameValue(I,N,V);
  419. if FTypeMap.Find(UTF8String(N))=Nil then
  420. AddToTypeMap(UTF8String(N),V);
  421. end;
  422. end;
  423. procedure TTSContext.PushScope(aScope: TJSSourceElements; aForwards : TStringList);
  424. begin
  425. if aScope=Nil then
  426. raise ETSToPas.Create(SErrCannotPushNilScope);
  427. Inc(FCurrentScopeIdx);
  428. if FCurrentScopeIdx>=Length(FScopes) then
  429. SetLength(FScopes,Length(FScopes)*2);
  430. FScopes[FCurrentScopeIdx].Source:= aScope;
  431. FScopes[FCurrentScopeIdx].Forwards:=aForwards;
  432. end;
  433. procedure TTSContext.PopScope(aScope: TJSSourceElements; aForwards : TStringList);
  434. begin
  435. if (aScope=Nil) then
  436. Raise ETSToPas.Create(SErrorCannotPopNilScope);
  437. if (aScope<>CurrentScope) or (aForwards<>CurrentForwards) then
  438. raise ETSToPas.Create(SErrCanOnlyPopToplevelScope);
  439. Dec(FCurrentScopeIdx);
  440. end;
  441. function TTSContext.ResolveTypeRef(D: TJSTypeDef): TJSTypeDef;
  442. begin
  443. Result:=D;
  444. While Result is TJSTypeReference do
  445. Result:=FindTypeDef(UTF8Encode((Result as TJSTypeReference).Name));
  446. if Result=Nil then
  447. Result:=D;
  448. end;
  449. function TTSContext.GetTypeName(const aTypeName: jsBase.TJSString; ForTypeDef: Boolean; UsePascal: Boolean): String;
  450. Function UsePascalType(Const aPascalType : string) : String;
  451. begin
  452. if UsePascal and ForTypeDef then
  453. Result:=StringReplace(UTF8Encode(aTypeName),' ','',[rfReplaceAll])
  454. else
  455. Result:=aPascalType;
  456. end;
  457. Var
  458. TN : UTF8String;
  459. begin
  460. Case aTypeName of
  461. 'union': TN:='JSValue';
  462. 'short': TN:=UsePascalType('Integer');
  463. 'long': TN:=UsePascalType('Integer');
  464. 'long long': TN:=UsePascalType('NativeInt');
  465. 'unsigned short': TN:=UsePascalType('Cardinal');
  466. 'unrestricted float': TN:=UsePascalType('Double');
  467. 'unrestricted double': TN:=UsePascalType('Double');
  468. 'unsigned long': TN:=UsePascalType('NativeInt');
  469. 'unsigned long long': TN:=UsePascalType('NativeInt');
  470. 'octet': TN:=UsePascalType('Byte');
  471. 'any' : TN:=UsePascalType('JSValue');
  472. 'number' : TN:=UsePascalType('Double');
  473. 'float' : TN:=UsePascalType('Double');
  474. 'double' : TN:=UsePascalType('Double');
  475. 'DOMString',
  476. 'USVString',
  477. 'ByteString' : TN:=UsePascalType('String');
  478. 'object' : TN:=UsePascalType('TJSObject');
  479. 'Error' : TN:=UsePascalType('TJSError');
  480. 'DOMException' : TN:=UsePascalType('TJSError');
  481. 'ArrayBuffer',
  482. 'DataView',
  483. 'Int8Array',
  484. 'Int16Array',
  485. 'Int32Array',
  486. 'Uint8Array',
  487. 'Uint16Array',
  488. 'Uint32Array',
  489. 'Uint8ClampedArray',
  490. 'Float32Array',
  491. 'Float64Array' : TN:='TJS'+UTF8Encode(aTypeName);
  492. else
  493. TN:=FindTypeAlias(aTypeName);
  494. end;
  495. Result:=TN;
  496. end;
  497. Function TTSContext.FindInNodes(aNodes : TJSElementNodes; const aName: String) : TJSTypeDeclaration;
  498. Var
  499. I : integer;
  500. N : TJSString;
  501. begin
  502. Result:=Nil;
  503. N:=UTF8Decode(aName);
  504. I:=aNodes.Count-1;
  505. While (Result=Nil) and (I>=0) do
  506. begin
  507. If aNodes[i].Node is TJSTypeDeclaration then
  508. begin
  509. Result:=aNodes[i].Node as TJSTypeDeclaration;
  510. if Result.Name<>N then
  511. Result:=Nil;
  512. end;
  513. Dec(I);
  514. end;
  515. end;
  516. function TTSContext.FindInScope(aScope : TJSSourceElements; const aName: String): TJSTypeDef;
  517. Var
  518. Decl :TJSTypeDeclaration;
  519. begin
  520. Result:=Nil;
  521. Decl:=FindInNodes(aScope.Enums,aName);
  522. if Decl=Nil then
  523. Decl:=FindInNodes(aScope.Types,aName);
  524. if Decl=Nil then
  525. Decl:=FindInNodes(aScope.Classes,aName);
  526. if Decl=Nil then
  527. Decl:=FindInNodes(aScope.Interfaces,aName);
  528. if Decl<>Nil then
  529. Result:=Decl.TypeDef;
  530. end;
  531. function TTSContext.FindTypeDef(const aName: String): TJSTypeDef;
  532. Var
  533. I : Integer;
  534. begin
  535. Result:=Nil;
  536. I:=FCurrentScopeIdx;
  537. While (Result=nil) and (I>=0) do
  538. begin
  539. Result:=FindInscope(FScopes[i].Source,aName);
  540. Dec(I);
  541. end;
  542. end;
  543. function TTSContext.FindTypeAlias(const aName: jsbase.TJSString): String;
  544. Var
  545. S : UTF8String;
  546. Parts : TStringArray;
  547. Obj : TObject;
  548. begin
  549. Result:='';
  550. if FTypeDeclarations.Count>0 then
  551. TypesToMap;
  552. S:=UTF8Encode(aName);
  553. Parts:=SplitString(S,'.');
  554. For S in Parts do
  555. begin
  556. Obj:=FTypeMap.Items[S];
  557. if Result<>'' then
  558. Result:=Result+'.';
  559. if (Obj is TPasData) then
  560. Result:=Result+TPasData(Obj).PasName
  561. else
  562. Result:=Result+S;
  563. end;
  564. end;
  565. procedure TTSContext.TypesToMap;
  566. Var
  567. I : Integer;
  568. el : TJSElement;
  569. N : String;
  570. begin
  571. For I:=0 to FTypeDeclarations.Count-1 do
  572. begin
  573. El:=TJSElement(FTypeDeclarations[i]);
  574. if El.Data=Nil then
  575. begin
  576. FConverter.AllocatePasName(El,'');
  577. end;
  578. if EL.Data<>Nil then
  579. begin
  580. if FConverter.NeedsTypeMap(El) then
  581. begin
  582. N:=UTF8Encode(TPasData(El.Data).OriginalName);
  583. if FTypeMap.Find(N)<>Nil then
  584. FConverter.DoLog(SErrIgnoringDuplicateTypeName, [N, TPasData(El.Data).PasName, EL.ClassName])
  585. else
  586. FTypeMap.Add(N,El.Data) ;
  587. end;
  588. end;
  589. end;
  590. FTypeDeclarations.Clear;
  591. end;
  592. function TTSContext.GetCurrentScope: TJSSourceElements;
  593. begin
  594. if CurrentScopeIdx>=0 then
  595. Result:=FScopes[CurrentScopeIdx].Source
  596. else
  597. Result:=Nil;
  598. end;
  599. function TTSContext.GetCurrentForwards: TStringList;
  600. begin
  601. if CurrentScopeIdx>=0 then
  602. Result:=FScopes[CurrentScopeIdx].Forwards
  603. else
  604. Result:=Nil;
  605. end;
  606. procedure TTSContext.DoGlobalFree(aEl: TJSElement);
  607. begin
  608. FTypeDeclarations.Extract(aEl);
  609. end;
  610. procedure TTSContext.AddToTypeMap(const aName: UTF8String; const aPasName: String);
  611. begin
  612. FTypeMap.Add(aName,FConverter.CreatePasName(UTF8Decode(aName),aPasName));
  613. end;
  614. procedure TTSContext.AddToTypeMap(const aName: jsbase.TJSString; const aPasName: String);
  615. begin
  616. AddToTypeMap(UTF8Encode(aName),aPasName);
  617. end;
  618. procedure TTSContext.AddToTypeMap(aType: TJSElement);
  619. begin
  620. // Writeln('aType : ',FTypeDeclarations.Count,': ',aType.Classname);
  621. FTypeDeclarations.Add(aType);
  622. end;
  623. procedure TTSContext.RemoveFromTypeMap(aType: TJSElement);
  624. begin
  625. // Writeln('Removing : ',FTypeDeclarations.Count,': ',aType.Classname, ' at ',FTypeDeclarations.IndexOf(aTYpe));
  626. FTypeDeclarations.Extract(aType);
  627. end;
  628. { TPasData }
  629. constructor TPasData.Create(const aOriginalName : jsBase.TJSString; const APasName : String);
  630. begin
  631. FOriginalName:=aOriginalName;
  632. FPasName:=APasName;
  633. end;
  634. destructor TPasData.destroy;
  635. begin
  636. // Writeln('Destroying ',Self.FOriginalName,'->',Self.Pasname);
  637. inherited destroy;
  638. end;
  639. { TTypescriptToPas }
  640. function TTypescriptToPas.CreateContext: TTSContext;
  641. begin
  642. Result:=TTSContext.Create(Self);
  643. end;
  644. function TTypescriptToPas.CreateScanner(aContext : TTSContext; S : TStream) : TJSScanner;
  645. begin
  646. Result:=TTSJSScanner.Create(S,FECMAVersion);
  647. Result.IsTypeScript:=True;
  648. end;
  649. function TTypescriptToPas.CreateParser(aContext : TTSContext;S : TJSScanner) : TJSParser;
  650. begin
  651. Result:=TTSJSParser.Create(S);
  652. TTSJSParser(Result).Context:=aContext;
  653. end;
  654. procedure TTypescriptToPas.DumpElements;
  655. Procedure DumpNodes(Const aSection : String; aList: TJSElementNodes);
  656. Var
  657. I : Integer;
  658. N : TJSElementNode;
  659. begin
  660. Writeln(aSection,': ',aList.Count,' elements');
  661. For I:=0 to aList.Count-1 do
  662. begin
  663. N:=Alist[i];
  664. Writeln(aSection,' element ',I,' : ',N.Node.ClassName);
  665. end;
  666. end;
  667. Var
  668. Els : TJSSourceElements;
  669. begin
  670. Els:=FElements.A as TJSSourceElements;
  671. DumpNodes('vars',Els.Vars);
  672. DumpNodes('statements',Els.Statements);
  673. DumpNodes('classes',Els.Classes);
  674. DumpNodes('types',Els.Types);
  675. DumpNodes('enums',Els.Enums);
  676. DumpNodes('functions',Els.Functions);
  677. DumpNodes('namespaces',Els.Namespaces);
  678. DumpNodes('modules',Els.Modules);
  679. end;
  680. function TTypescriptToPas.ResolveTypeRef(D: TJSTypeDef): TJSTypeDef;
  681. begin
  682. Result:=Context.ResolveTypeRef(D);
  683. end;
  684. procedure TTypescriptToPas.SetFLinkStatements(AValue: TStrings);
  685. begin
  686. if FLinkStatements=AValue then Exit;
  687. FLinkStatements.Assign(AValue);
  688. end;
  689. function TTypescriptToPas.CheckUnionTypeDefinition(D: TJSTypeDef): TJSUnionTypeDef;
  690. begin
  691. Result:=Nil;
  692. D:=ResolveTypeRef(D);
  693. If (D is TJSUnionTypeDef) then
  694. Result:=D as TJSUnionTypeDef;
  695. end;
  696. procedure TTypescriptToPas.Parse;
  697. Var
  698. F : TStream;
  699. S : TJSScanner;
  700. P : TJSParser;
  701. El : TJSElement;
  702. begin
  703. FreeAndNil(FElements); // In case parse is called multiple times
  704. P:=Nil;
  705. F:=InputStream;
  706. if (F=Nil) then
  707. F:=TFileStream.Create(InputFileName,fmOpenRead or fmShareDenyWrite);
  708. try
  709. S:=CreateScanner(Context,F);
  710. P:=CreateParser(Context,S);
  711. El:=P.Parse;
  712. if not (El is TJSFunctionBody) then
  713. begin
  714. EL.Free;
  715. raise ETStoPas.Create(SErrParseResultIsNotFunctionBody);
  716. end;
  717. FElements:=El as TJSFunctionBody;
  718. // DumpElements;
  719. finally
  720. P.Free;
  721. S.Free;
  722. if F<>InputStream then
  723. F.Free;
  724. end;
  725. end;
  726. function TTypescriptToPas.GetExternalMemberName(const aName : jsBase.TJSString) : string;
  727. begin
  728. if FCurrentNameSpace<>'' then
  729. Result:=FCurrentNameSpace+'.'+UTF8Encode(aName)
  730. else
  731. Result:=UTF8Encode(aName);
  732. end;
  733. function TTypescriptToPas.GetName(ADef: TJSElement): String;
  734. begin
  735. If Assigned(ADef) and (TObject(ADef.Data) is TPasData) then
  736. Result:=TPasData(ADef.Data).PasName
  737. else if aDef is TJSNamedElement then
  738. Result:=EscapeKeyWord(UTF8Encode(TJSNamedElement(ADef).Name))
  739. else
  740. Result:='';
  741. end;
  742. function TTypescriptToPas.GetName(ADef: TJSTypedParam): String;
  743. begin
  744. Result:=EscapeKeyWord(UTF8Encode(aDef.Name));
  745. end;
  746. function TTypescriptToPas.GetName(ADef: TJSFuncDef): String;
  747. begin
  748. Result:=EscapeKeyWord(UTF8Encode(aDef.Name));
  749. end;
  750. function TTypescriptToPas.HaveConsts(aList: TJSSourceElements): Boolean;
  751. Var
  752. I : Integer;
  753. D : TJSVariableStatement;
  754. begin
  755. Result:=False;
  756. For I:=0 to aList.Vars.Count-1 do
  757. begin
  758. D:=aList.Vars[i].Node as TJSVariableStatement;
  759. if (D.VarType=vtConst) then
  760. Exit(True);
  761. end;
  762. end;
  763. function TTypescriptToPas.GetTypeName(const aTypeName: jsBase.TJSString; ForTypeDef: Boolean): String;
  764. begin
  765. Result:=Context.GetTypeName(aTypeName,ForTypeDef,(coUseNativeTypeAliases in Options));
  766. end;
  767. function TTypescriptToPas.GetFixedValueTypeName(ATypeDef : TJSFixedValueReference) : String;
  768. begin
  769. if Not (Assigned(ATypeDef.FixedValue) and Assigned(ATypeDef.FixedValue.Value)) then
  770. Result:='JSValue'
  771. else
  772. Case ATypeDef.FixedValue.Value.ValueType of
  773. jstBoolean : Result:='Boolean';
  774. jstNumber : Result:='Double';
  775. jstString : Result:='String';
  776. jstObject : Result:='TJSObject';
  777. else
  778. Result:='JSValue';
  779. end;
  780. end;
  781. function TTypescriptToPas.GetTypeName(aTypeDef : TJSTypeDef; ForTypeDef : Boolean = False): String;
  782. Var
  783. S : jsbase.TJSString;
  784. begin
  785. if (aTypeDef.Data is TPasData) then
  786. Result:=TPasData(aTypeDef.Data).PasName
  787. else if ATypeDef is TJSTypeReference then
  788. begin
  789. S:=TJSTypeReference(aTypeDef).Name;
  790. Result:=GetTypeName(S,ForTypeDef)
  791. end
  792. else if ATypeDef is TJSArrayTypeDef then
  793. Result:='array of '+GetTypeName(TJSArrayTypeDef(aTypeDef).BaseType,ForTypeDef)
  794. else if ATypeDef is TJSUnionOrIntersectTypeDef then
  795. Result:='jsvalue'
  796. else if ATypeDef is TJSGenericTypeRef then
  797. Result:=GetTypeName(TJSGenericTypeRef(aTypeDef).BaseType,ForTypeDef)
  798. else if ATypeDef is TJSArrowFunctionTypeDef then
  799. Result:='procedure'
  800. else if ATypeDef is TJSFixedValueReference then
  801. Result:=GetFixedValueTypeName(ATypeDef as TJSFixedValueReference)
  802. else
  803. raise ETSToPas.CreateFmt(SErrCannotGetTypeNameFromType, [aTypeDef.ClassName, aTypeDef.Line, aTypeDef.Column]);
  804. end;
  805. function TTypescriptToPas.WriteProperties(aClass: TJSClassDeclaration): Integer;
  806. Var
  807. I : Integer;
  808. D : TJSVariableStatement;
  809. begin
  810. Result:=0;
  811. For I:=0 to aClass.Members.Vars.Count-1 do
  812. if ExportNode(aClass.Members.Vars[i]) then
  813. begin
  814. D:=aClass.Members.Vars[i].Node as TJSVariableStatement;
  815. if (D.VarType=vtVar) then
  816. begin
  817. WritePropertyDeclaration(D);
  818. Inc(Result);
  819. end;
  820. end;
  821. end;
  822. function TTypescriptToPas.GetAccessName(aAccess : TAccessibility) : string;
  823. Const
  824. AccessNames : Array[TAccessibility] of string
  825. = ('','Private','Protected','Public');
  826. begin
  827. Result:=AccessNames[aAccess];
  828. end;
  829. function TTypescriptToPas.WriteProperties(aAccess: TAccessibility; aMembers: TJSElementNodes): Integer;
  830. Var
  831. EN : TJSElementNode;
  832. P : TJSPropertyDeclaration;
  833. OK : Boolean;
  834. begin
  835. Result:=0;
  836. For EN in aMembers do
  837. begin
  838. if EN.Node is TJSPropertyDeclaration then
  839. begin
  840. P:=TJSPropertyDeclaration(EN.Node);
  841. if (P.Accessibility=aAccess) then
  842. begin
  843. if P.IsReadOnly then
  844. OK:=WriteReadOnlyProperty(P)
  845. else
  846. OK:=WritePropertyDef(P);
  847. if Ok then
  848. Inc(Result);
  849. end;
  850. end;
  851. end;
  852. end;
  853. function TTypescriptToPas.GetGenericParams(aTypeParams: TJSElementNodes) : String;
  854. Var
  855. I : Integer;
  856. aName: jsBase.TJSString;
  857. N : TJSTypeDef;
  858. begin
  859. Result:='';
  860. if aTypeParams=nil then exit;
  861. For I:=0 to aTypeParams.Count-1 do
  862. if (aTypeParams[i].Node is TJSTypeReference) then
  863. begin
  864. aName:=(aTypeParams[i].Node as TJSTypeReference).Name;
  865. if Result<>'' then
  866. Result:=Result+',';
  867. Result:=Result+UTF8Encode(aName);
  868. end
  869. else if (aTypeParams[i].Node is TJSNamedParamTypeDef) then
  870. begin
  871. N:=(aTypeParams[i].Node as TJSNamedParamTypeDef).ParamName;
  872. if (N is TJSTypeReference) then
  873. aName:=(N as TJSTypeReference).Name
  874. else
  875. raise ETSToPas.CreateFmt(SErrUnsupportedNamedParamType, [ATypeParams[I].Node.ClassName]);
  876. if Result<>'' then
  877. Result:=Result+',';
  878. Result:=Result+UTF8Encode(aName);
  879. end
  880. else
  881. raise ETSToPas.CreateFmt(ResUnsupportedTypeParameter, [ATypeParams[I].Node.ClassName]);
  882. if Result<>'' then
  883. Result:='<'+Result+'>';
  884. end;
  885. Function TTypescriptToPas.GetAliasTypeAsString(aTypeDef : TJSTypeReference; asPascal, asSubType: Boolean) : string;
  886. begin
  887. if asPascal then
  888. Result:=GetTypeName(aTypeDef.Name,True)
  889. else
  890. Result:=UTF8Encode(aTypeDef.Name);
  891. end;
  892. procedure TTypescriptToPas.WriteAliasTypeDef(const aPasName : string; const aOrgName : jsBase.TJSString; aTypeParams: TJSElementNodes; aTypeDef : TJSTypeReference);
  893. Var
  894. TN, gen, genparams: String;
  895. begin
  896. TN:=GetAliasTypeAsString(aTypeDef,True,False);
  897. genparams:=GetGenericParams(aTypeParams);
  898. if (genparams<>'') then
  899. gen:='generic ';
  900. AddLn('%s%s%s = %s;',[gen,aPasName,genparams,TN]);
  901. end;
  902. procedure TTypescriptToPas.WriteImplementation;
  903. begin
  904. end;
  905. Procedure TTypescriptToPas.WritePropertyDeclaration(D : TJSVariableStatement);
  906. begin
  907. end;
  908. procedure TTypescriptToPas.Getoptions(L : TStrings);
  909. Var
  910. S : String;
  911. I : Integer;
  912. begin
  913. L.Add('Automatically generated file by '+ClassName+' on '+FormatDateTime('yyyy-mm-dd hh:nn:ss',Now));
  914. L.Add('');
  915. L.Add('Used command-line options : ');
  916. For I:=1 to ParamCount do
  917. L.Add(ParamStr(i));
  918. L.Add('');
  919. L.Add('Command-line options translate to: ');
  920. L.Add('');
  921. S:=SetToString(PtypeInfo(TypeInfo(TConversionOptions)),Integer(OPtions),True);
  922. L.Add('Options : '+S);
  923. L.Add('Keyword prefix : '+KeywordPrefix);
  924. L.Add('Keyword suffix : '+KeywordSuffix);
  925. L.Add('Class prefix : '+ClassPrefix);
  926. L.Add('Class suffix : '+ClassSuffix);
  927. L.Add('Field prefix : '+FieldPrefix);
  928. Str(ECMAversion,S);
  929. L.Add('ECMALversion : '+S);
  930. if TypeAliases.Count>0 then
  931. begin
  932. L.Add('Type aliases:');
  933. L.AddStrings(Self.TypeAliases);
  934. end;
  935. end;
  936. procedure TTypescriptToPas.AddOptionsToHeader;
  937. Var
  938. L : TStrings;
  939. begin
  940. L:=TStringList.Create;
  941. try
  942. GetOptions(L);
  943. Comment(L);
  944. finally
  945. L.Free;
  946. end;
  947. end;
  948. procedure TTypescriptToPas.PushNameScope;
  949. begin
  950. Inc(FScopeIdx);
  951. FScopeNameList[FScopeIdx]:=TFPStringHashTable.Create;
  952. end;
  953. procedure TTypescriptToPas.PopNameScope;
  954. begin
  955. if FScopeIdx<0 then
  956. exit;
  957. FreeAndNil(FScopeNameList[FScopeIdx]);
  958. Dec(FScopeIdx);
  959. end;
  960. function TTypescriptToPas.NameScopeHas(const aName: string): Boolean;
  961. begin
  962. Result:=FScopeIdx>=0;
  963. if Result then
  964. Result:=Assigned(FScopeNameList[FScopeIdx].Find(aName));
  965. end;
  966. procedure TTypescriptToPas.AddToNameScope(const aName: String; aData: jsbase.TJSString);
  967. begin
  968. if FScopeIdx>=0 then
  969. FScopeNameList[FScopeIdx].Add(aName,UTF8Encode(aData));
  970. end;
  971. procedure TTypescriptToPas.WriteIncludeInterfaceCode;
  972. Var
  973. S : String;
  974. begin
  975. For S in IncludeInterfaceCode do
  976. Addln(S);
  977. end;
  978. constructor TTypescriptToPas.Create(Aowner: TComponent);
  979. begin
  980. inherited Create(Aowner);
  981. ECMaVersion:=ecma2021;
  982. FieldPrefix:='F';
  983. ClassPrefix:='T';
  984. ClassSuffix:='';
  985. Switches.Add('modeswitch externalclass');
  986. FTypeAliases:=TStringList.Create;
  987. TStringList(FTypeAliases).Sorted:=true;
  988. TStringList(FTypeAliases).Duplicates:=dupIgnore;
  989. FPasNameList:=TFPObjectList.Create(True);
  990. FIncludeInterfaceCode:=TStringList.Create;
  991. FIncludeImplementationCode:=TStringList.Create;
  992. FLinkStatements:=TStringList.Create;
  993. FForwards:=TStringList.Create;
  994. DefaultClassParent:='TJSObject';
  995. FOptions:=[];
  996. end;
  997. destructor TTypescriptToPas.Destroy;
  998. begin
  999. FreeAndNil(FForwards);
  1000. FreeAndNil(FLinkStatements);
  1001. FreeAndNil(FElements);
  1002. FreeAndNil(FIncludeInterfaceCode);
  1003. FreeAndNil(FIncludeImplementationCode);
  1004. FreeAndNil(FTypeAliases);
  1005. FreeAndNil(FPasNameList);
  1006. inherited Destroy;
  1007. end;
  1008. procedure TTypescriptToPas.WriteVariable(aVar : TJSVarDeclaration);
  1009. Var
  1010. Src,aPasName,aTypeName: String;
  1011. aExportName : TJSString;
  1012. begin
  1013. aPasName:=GetName(aVar);
  1014. aExportName:=aVar.Name;
  1015. aTypeName:=GetTypeName(aVar.Typed,False);
  1016. Src:=aPasName + ' : '+aTypeName+';';
  1017. Src:=Src+' external name '''+Utf8Encode(aExportName)+''';';
  1018. AddLn(Src);
  1019. end;
  1020. procedure TTypescriptToPas.WriteVariables(Vars : TJSElementNodes);
  1021. Var
  1022. I : Integer;
  1023. begin
  1024. For I:=0 to Vars.Count-1 do
  1025. if ExportNode(Vars.Nodes[i]) then
  1026. WriteVariable(Vars.Nodes[i].Node as TJSVarDeclaration);
  1027. end;
  1028. procedure TTypescriptToPas.WriteSourceElements(SourceElements : TJSSourceElements; aNamespace : TJSString);
  1029. Var
  1030. NS : String;
  1031. HasTypes : Boolean;
  1032. Written : Integer;
  1033. Fwds : TStringList;
  1034. begin
  1035. NS:=FCurrentNameSpace;
  1036. Fwds:=TStringList.Create;
  1037. try
  1038. if (FCurrentNameSpace<>'') then
  1039. FCurrentNameSpace:=FCurrentNameSpace+'.';
  1040. FCurrentNameSpace:=FCurrentNameSpace+NS;
  1041. Context.PushScope(SourceElements,Fwds);
  1042. HasTypes:=(SourceElements.Types.Count>0) or (SourceElements.Enums.Count>0);
  1043. HasTypes:=HasTypes or (SourceElements.Namespaces.Count>0) or (SourceElements.Modules.Count>0);
  1044. HasTypes:=HasTypes or (SourceElements.Classes.Count>0) or (SourceElements.Interfaces.Count>0);
  1045. HasTypes:=HasTypes or HasIndirectTypeDefs(SourceElements.Functions);
  1046. HasTypes:=HasTypes or HasIndirectTypeDefs(SourceElements.Types);
  1047. HasTypes:=HasTypes or HasIndirectTypeDefs(SourceElements.Vars);
  1048. if HasTypes then
  1049. begin
  1050. EnsureSection(csType);
  1051. Indent;
  1052. Written:=WriteForwardClassDefs(SourceElements.Interfaces);
  1053. Written:=Written+WriteForwardClassDefs(SourceElements.Classes);
  1054. Written:=Written+WriteForwardClassDefs(SourceElements.Namespaces);
  1055. Written:=Written+WriteForwardClassDefs(SourceElements.Modules);
  1056. Written:=Written+WriteForwardClassDefs(SourceElements.Types); // object types
  1057. If Written>0 then
  1058. AddLn('');
  1059. WriteIndirectTypeDefs(SourceElements.Types);
  1060. WriteIndirectTypeDefs(SourceElements.Vars);
  1061. WriteTypeDefs(SourceElements.Types);
  1062. WriteTypeDefs(SourceElements.Enums);
  1063. WriteIndirectTypeDefs(SourceElements.Functions);
  1064. WriteClassDefs(SourceElements.Classes);
  1065. //
  1066. WriteNamespaceDefs(SourceElements.Namespaces);
  1067. WriteModuleDefs(SourceElements.Modules);
  1068. WriteInterfaceDefs(SourceElements.Interfaces);
  1069. {
  1070. WriteEnumDefs(Context.Definitions);
  1071. WriteCallbackDefs(Context.Definitions);
  1072. WriteDictionaryDefs(Context.Definitions);
  1073. }
  1074. Undent;
  1075. AddLn('');
  1076. end;
  1077. if SourceElements.Vars.Count>0 then
  1078. begin
  1079. EnsureSection(csVar);
  1080. Indent;
  1081. WriteVariables(SourceElements.Vars);
  1082. Undent;
  1083. end;
  1084. if SourceElements.Functions.Count>0 then
  1085. begin
  1086. WriteFunctionDefs(SourceElements.Functions,aNameSpace='');
  1087. end;
  1088. finally
  1089. Context.PopScope(SourceElements,fwds);
  1090. Fwds.Free;
  1091. FCurrentNamespace:=NS;
  1092. end;
  1093. end;
  1094. procedure TTypescriptToPas.WriteLinkStatements(aList : TStrings);
  1095. Var
  1096. i : Integer;
  1097. begin
  1098. For I:=0 to aList.Count-1 do
  1099. AddLn('{$linklib '+aList[i]+'}');
  1100. end;
  1101. procedure TTypescriptToPas.WriteImports(SourceElements : TJSSourceElements);
  1102. Var
  1103. I : integer;
  1104. Imps : TJSImportStatement;
  1105. PE : TJSPrimaryExpressionIdent;
  1106. CE : TJSCallExpression;
  1107. begin
  1108. For I:=0 to SourceElements.Statements.Count-1 do
  1109. if SourceElements.Statements[i].Node is TJSImportStatement then
  1110. begin
  1111. Imps:=TJSImportStatement(SourceElements.Statements[i].Node);
  1112. if (Imps.Expression is TJSCallExpression) then
  1113. begin
  1114. CE:=Imps.Expression as TJSCallExpression;
  1115. if CE.Expr is TJSPrimaryExpressionIdent then
  1116. begin
  1117. PE:=CE.Expr as TJSPrimaryExpressionIdent;
  1118. if (Pe.Name='require')
  1119. and (CE.Args.Count=1)
  1120. and (CE.Args.Elements[0].Expr is TJSLiteral) then
  1121. begin
  1122. Comment(SCommentRequiredImportFile+Utf8Encode((CE.Args.Elements[0].expr as TJSLiteral).Value.AsString));
  1123. end;
  1124. end;
  1125. end
  1126. else
  1127. Comment(Format(SCommentImportFile, [Imps.ModuleName]))
  1128. end;
  1129. end;
  1130. procedure TTypescriptToPas.WritePascal;
  1131. Var
  1132. SourceElements : TJSSourceElements;
  1133. begin
  1134. SourceElements:=FElements.A as TJSSourceElements;
  1135. if Not IsRaw then
  1136. begin
  1137. CreateUnitClause;
  1138. if not (coSkipImportStatements in Options) then
  1139. WriteImports(SourceElements);
  1140. CreateHeader;
  1141. if coaddOptionsToheader in Options then
  1142. AddOptionsToHeader;
  1143. Addln('{$INTERFACES CORBA}');
  1144. WriteLinkStatements(FLinkStatements);
  1145. end;
  1146. WriteSourceElements(SourceElements,'');
  1147. if not IsRaw then
  1148. begin
  1149. WriteIncludeInterfaceCode;
  1150. Addln('');
  1151. AddLn('implementation');
  1152. WriteImplementation;
  1153. AddLn('end.');
  1154. end;
  1155. if OutputFileName<>'' then
  1156. Source.SaveToFile(OutputFileName);
  1157. end;
  1158. function TTypescriptToPas.NeedsTypeMap(El: TJSElement): Boolean;
  1159. begin
  1160. Result:=true;
  1161. if El is TJSInterfaceDeclaration then
  1162. Result:=not HaveClass(TJSInterfaceDeclaration(El).Name)
  1163. else if El is TJSNameSpaceDeclaration then
  1164. Result:=not (HaveClass(TJSNameSpaceDeclaration(El).Name)
  1165. or HaveModule(TJSNameSpaceDeclaration(El).Name))
  1166. end;
  1167. function TTypescriptToPas.BaseUnits: String;
  1168. begin
  1169. Result:='SysUtils, JS'
  1170. end;
  1171. function TTypescriptToPas.CreatePasName(const aOriginal: jsBase.TJSString; const aName: String): TPasData;
  1172. begin
  1173. Result:=TPasData.Create(aOriginal,aName);
  1174. FPasNameList.Add(Result);
  1175. end;
  1176. function TTypescriptToPas.AllocatePasName(D: TJSElement; ParentName: String): TPasData;
  1177. Var
  1178. Org : TJSString;
  1179. CN : String;
  1180. CD : TJSClassDeclaration absolute D;
  1181. AD : TJSAmbientClassDeclaration absolute D;
  1182. ID : TJSInterfaceDeclaration absolute D;
  1183. VD : TJSVarDeclaration absolute D;
  1184. TD : TJSTypeDeclaration absolute D;
  1185. FS : TJSFunctionStatement absolute D;
  1186. ND : TJSNameSpaceDeclaration absolute D;
  1187. MD : TJSModuleDeclaration absolute D;
  1188. OE : TJSObjectTypeElementDef absolute D;
  1189. OO : TJSObjectTypeDef absolute D;
  1190. begin
  1191. Result:=Nil;
  1192. if D Is TJSAmbientClassDeclaration then
  1193. begin
  1194. Org:=AD.Name;
  1195. CN:=ClassPrefix+UTF8Encode(Org)+ClassSuffix;
  1196. Result:=CreatePasname(Org,CN);
  1197. AllocatePasNames(AD.ClassDef.Values,UTF8Encode(AD.Name));
  1198. end
  1199. else if D Is TJSClassDeclaration then
  1200. begin
  1201. Org:=CD.Name;
  1202. CN:=ClassPrefix+UTF8Encode(Org)+ClassSuffix;
  1203. Result:=CreatePasname(Org,CN);
  1204. AllocatePasNames(CD.members,UTF8Encode(CD.Name));
  1205. end
  1206. else if D Is TJSInterfaceDeclaration then
  1207. begin
  1208. Org:=ID.Name;
  1209. CN:=ClassPrefix+UTF8Encode(Org)+ClassSuffix;
  1210. Result:=CreatePasname(Org,CN);
  1211. AllocatePasNames(ID.Values,EscapeKeyWord(UTF8Encode(ID.Name)));
  1212. end
  1213. else if D Is TJSVarDeclaration then
  1214. begin
  1215. Org:=VD.Name;
  1216. Result:=CreatePasName(Org, EscapeKeyWord(UTF8Encode(Org)));
  1217. end
  1218. else if D Is TJSFunctionStatement then
  1219. begin
  1220. Org:=FS.aFunction.Name;
  1221. Result:=CreatePasName(Org, EscapeKeyWord(UTF8Encode(Org)));
  1222. end
  1223. else if D Is TJSTypeDeclaration then
  1224. begin
  1225. Org:=TD.Name;
  1226. Result:=CreatePasName(Org, EscapeKeyWord('T'+UTF8Encode(Org)));
  1227. end
  1228. else if D Is TJSNameSpaceDeclaration then
  1229. begin
  1230. Org:=UTF8Decode(ClassPrefix)+ND.Name+UTF8Decode(ClassSuffix);
  1231. Result:=CreatePasName(Org, EscapeKeyWord(UTF8Encode(Org)));
  1232. end
  1233. else if D Is TJSModuleDeclaration then
  1234. begin
  1235. Org:=UTF8Decode(ClassPrefix)+MD.Name+UTF8Decode(ClassSuffix);
  1236. Result:=CreatePasName(Org, EscapeKeyWord(UTF8Encode(Org)));
  1237. end
  1238. else if D Is TJSObjectTypeElementDef then
  1239. begin
  1240. Org:=OE.Name;
  1241. Result:=CreatePasName(Org, EscapeKeyWord(UTF8Encode(Org)));
  1242. end
  1243. else if D Is TJSObjectTypeDef then
  1244. begin
  1245. Org:=OO.Name;
  1246. if Org<>'' then
  1247. Result:=CreatePasName(Org, EscapeKeyWord(UTF8Encode(Org)));
  1248. end
  1249. else
  1250. Raise ETSToPas.CreateFmt('Unsupported type to get name from: "%s"',[D.ClassName]);
  1251. D.Data:=Result;
  1252. if Verbose and (Result<>Nil) and (Result.PasName<>UTF8Encode(Org)) then
  1253. begin
  1254. if (ParentName<>'') then
  1255. ParentName:=ParentName+'.';
  1256. DoLog(SLogRenamedType, [ParentName+UTF8Encode(Org), TPasData(D.Data).PasName]);
  1257. end;
  1258. end;
  1259. Function TTypescriptToPas.TypeNeedsTypeName(aType: TJSElement; IgnoreData : Boolean; IsResultType : Boolean = False): Boolean;
  1260. begin
  1261. if (aType=Nil) then // For example a parameter can have no type.
  1262. exit(False);
  1263. Result:=IgnoreData or (aType.Data=Nil);
  1264. if Result then
  1265. Result:=(aType is TJSArrowFunctionTypeDef)
  1266. or (aType is TJSObjectTypeDef)
  1267. or (aType is TJSTupleTypeDef)
  1268. or ((aType is TJSArrayTypeDef)
  1269. and (IsResultType or TypeNeedsTypeName(TJSArrayTypeDef(aType).BaseType,IgnoreData,True)));
  1270. end;
  1271. Function TTypescriptToPas.AllocateTypeName(aType: TJSElement; const aPrefix,aName : String): Integer;
  1272. Var
  1273. aTypeName : String;
  1274. begin
  1275. Result:=1;
  1276. aTypeName:=aPrefix+aName;
  1277. // Writeln('AITD Typename : ',aPrefix,', Parn: ',UTF8Decode(aName), ' Typen : ',aTypeName,' esc : ',EscapeKeyWord('T'+aTypeName));
  1278. aType.Data:=CreatePasName(UTF8Decode(aName), EscapeKeyWord('T'+aTypeName));
  1279. end;
  1280. function TTypescriptToPas.AllocateIndirectTypeDef(El : TJSElement; const aPrefix,aName : String) : Integer;
  1281. var
  1282. FD : TJSFuncDef;
  1283. SubPrefix : String;
  1284. begin
  1285. // Writeln('AITD element: ',El.ClassName,' Prefix: ',aPrefix);
  1286. SubPrefix:=aPrefix;
  1287. if aName<>'' then
  1288. SubPrefix:=SubPrefix+aName+'_';
  1289. Result:=0;
  1290. if (el is TJSArrowFunctionTypeDef) then
  1291. begin
  1292. if el.Data=Nil then
  1293. AllocateTypeName(El,aPrefix,aName);
  1294. FD:=TJSArrowFunctionTypeDef(El).aFunction;
  1295. Result:=AllocateIndirectTypeDefs(FD,SubPrefix);
  1296. end
  1297. else if (el is TJSObjectTypeDef) then
  1298. begin
  1299. Inc(Result);
  1300. if el.Data=Nil then
  1301. AllocateTypeName(El,aPrefix,aName);
  1302. Result:=Result+AllocateIndirectTypeDefs(TJSObjectTypeDef(El).Values,SubPrefix);
  1303. end
  1304. else if (el is TJSTupleTypeDef) then
  1305. begin
  1306. Inc(Result);
  1307. AllocateTypeName(El,aPrefix,aName);
  1308. end
  1309. else if (el is TJSArrayTypeDef) then
  1310. begin
  1311. Inc(Result);
  1312. if TypeNeedsTypeName(TJSArrayTypeDef(el).BaseType,False,True) then
  1313. Result:=Result+AllocateIndirectTypeDef(TJSArrayTypeDef(el).BaseType,SubPrefix,'Item');
  1314. AllocateTypeName(El,aPrefix,aName);
  1315. end;
  1316. end;
  1317. function TTypescriptToPas.AllocateIndirectTypeDefs(aElements: TJSElementNodes; const aPrefix : String): Integer;
  1318. var
  1319. PD : TJSPropertyDeclaration;
  1320. VD : TJSVarDeclaration;
  1321. EN : TJSElementNode;
  1322. FD : TJSFuncDef;
  1323. begin
  1324. Result:=0;
  1325. // Writeln('AITD List, prefix : ',aPrefix);
  1326. For EN in aElements do
  1327. begin
  1328. FD:=Nil;
  1329. if EN.Node is TJSFunctionStatement then
  1330. begin
  1331. FD:=TJSFunctionStatement(EN.Node).AFunction;
  1332. AllocateIndirectTypeDefs(FD,aPrefix);
  1333. end
  1334. else if EN.Node is TJSMethodDeclaration then
  1335. begin
  1336. FD:=TJSMethodDeclaration(EN.Node).FuncDef;
  1337. AllocateIndirectTypeDefs(FD,aPrefix);
  1338. end
  1339. else if (EN.Node is TJSPropertyDeclaration) then
  1340. begin
  1341. PD:=EN.Node as TJSPropertyDeclaration;
  1342. if TypeNeedsTypeName(PD.ElementType,False,True) then
  1343. Result:=Result+AllocateIndirectTypeDef(PD.ElementType,aPrefix,GetName(PD));
  1344. end
  1345. else if (EN.Node is TJSVarDeclaration) then
  1346. begin
  1347. VD:=EN.Node as TJSVarDeclaration;
  1348. if (VD.Typed is TJSObjectTypeDef) then
  1349. Result:=Result+AllocateIndirectTypeDef(VD.Typed,aPrefix,GetName(VD));
  1350. end;
  1351. end;
  1352. end;
  1353. Function TTypescriptToPas.AllocateIndirectTypeDefs(aParams: TJSTypedParams; const aPrefix : String): Integer;
  1354. Var
  1355. I : Integer;
  1356. aParam : TJSTypedParam;
  1357. begin
  1358. // Writeln('AITD params prefix : ',aPrefix);
  1359. Result:=0;
  1360. For I:=0 to aParams.Count-1 do
  1361. begin
  1362. aParam:=aParams[i];
  1363. if TypeNeedsTypeName(aParam.Node,False) then
  1364. begin
  1365. AllocateIndirectTypeDef(aParam.Node,aPrefix,UTF8Encode(aParam.Name));
  1366. // Result:=Result+AllocateTypeName(aParam.Node,aPrefix,UTF8Encode(aParam.Name));
  1367. end;
  1368. end;
  1369. end;
  1370. function TTypescriptToPas.AllocateIndirectTypeDefs(FD : TJSFuncDef; const aPrefix : String): Integer;
  1371. Var
  1372. fn,aTypePrefix : String;
  1373. begin
  1374. fn:=UTF8Encode(FD.Name);
  1375. if fn<>'' then
  1376. FN:=FN+'_';
  1377. aTypePrefix:=aPrefix+FN;
  1378. // Writeln('AITD func (',fd.Name,') prefix : ',aPrefix,' Type prefix: ',aTypePrefix);
  1379. Result:=AllocateIndirectTypeDefs(FD.TypedParams,aTypePrefix);
  1380. if TypeNeedsTypeName(FD.ResultType,False,True) then
  1381. Result:=Result+AllocateIndirectTypeDef(FD.ResultType,aTypePrefix,'Result');
  1382. end;
  1383. procedure TTypescriptToPas.SetTypeAliases(AValue: TStrings);
  1384. begin
  1385. if FTypeAliases=AValue then Exit;
  1386. FTypeAliases.Assign(AValue);
  1387. end;
  1388. procedure TTypescriptToPas.SetIncludeInterfaceCode(AValue: TStrings);
  1389. begin
  1390. if FIncludeInterfaceCode=AValue then Exit;
  1391. FIncludeInterfaceCode.Assign(AValue);
  1392. end;
  1393. procedure TTypescriptToPas.SetIncludeImplementationCode(AValue: TStrings);
  1394. begin
  1395. if FIncludeImplementationCode=AValue then Exit;
  1396. FIncludeImplementationCode.Assign(AValue);
  1397. end;
  1398. function TTypescriptToPas.GetIsRaw: Boolean;
  1399. begin
  1400. Result:=coRaw in Options;
  1401. end;
  1402. procedure TTypescriptToPas.AllocatePasNames(FD : TJSFuncDef; aPrefix: String = '');
  1403. begin
  1404. AllocateIndirectTypeDefs(FD.TypedParams,aPrefix);
  1405. if TypeNeedsTypeName(FD.ResultType,False,True) then
  1406. AllocateIndirectTypeDef(FD.ResultType,aPrefix,'Result');
  1407. end;
  1408. procedure TTypescriptToPas.AllocatePasNames(aList : TJSElementNodes; ParentName: String = '');
  1409. Var
  1410. I : Integer;
  1411. N : TJSElement;
  1412. TD : TJSTypeDeclaration absolute N;
  1413. MD : TJSMethodDeclaration absolute N;
  1414. AD : TJSArrowFunctionTypeDef;
  1415. PD : TJSPropertyDeclaration absolute N;
  1416. lParentName,aPrefix : String;
  1417. begin
  1418. lParentName:=ParentName;
  1419. if lParentName<>'' then
  1420. lParentName:=lParentName+'_';
  1421. For I:=0 to aList.Count-1 do
  1422. begin
  1423. APrefix:='';
  1424. N:=aList.Nodes[i].Node;
  1425. AllocatePasName(N,ParentName);
  1426. if N is TJSAmbientClassDeclaration then
  1427. AllocatePasNames(TJSAmbientClassDeclaration(N).ClassDef.Values,lParentName)
  1428. else if N is TJSMembersDeclaration then
  1429. AllocatePasNames(TJSMembersDeclaration(N).Members)
  1430. else if (N is TJSTypeDeclaration) then
  1431. begin
  1432. if (TD.TypeDef is TJSArrowFunctionTypeDef) then
  1433. begin
  1434. aPrefix:=StringReplace(GetName(TD),'&','',[rfReplaceAll])+'_';
  1435. AD:=TD.TypeDef as TJSArrowFunctionTypeDef;
  1436. AllocatePasNames(AD.aFunction,aPrefix);
  1437. end;
  1438. end
  1439. else if (N is TJSMethodDeclaration) then
  1440. begin
  1441. if Assigned(MD.FuncDef) then
  1442. begin
  1443. aPrefix:=StringReplace(GetName(MD),'&','',[rfReplaceAll])+'_';
  1444. if (lParentName<>'') and not (coLocalArgumentTypes in Options) then
  1445. aPrefix:=lParentName+aPrefix;
  1446. AllocatePasNames(MD.FuncDef,aPrefix);
  1447. end;
  1448. end
  1449. else if (N is TJSPropertyDeclaration) then
  1450. begin
  1451. if Assigned(PD.ElementType) then
  1452. if TypeNeedsTypeName(PD.ElementType,False,True) then
  1453. begin
  1454. AllocateTypeName(PD.ElementType,lParentName,GetName(PD));
  1455. aPrefix:=StringReplace(GetName(PD),'&','',[rfReplaceAll]);
  1456. AllocateIndirectTypeDef(PD.ElementType,lParentName,aPrefix);
  1457. end;
  1458. end;
  1459. end;
  1460. end;
  1461. procedure TTypescriptToPas.AllocatePasNames(aList : TJSSourceElements; ParentName: String = '');
  1462. begin
  1463. AllocatePasNames(aList.Types,ParentName);
  1464. AllocatePasNames(aList.Enums,ParentName);
  1465. AllocatePasNames(aList.Vars,ParentName);
  1466. AllocateIndirectTypeDefs(aList.Vars,'');
  1467. AllocatePasNames(aList.Functions,ParentName);
  1468. AllocateIndirectTypeDefs(aList.Functions,'');
  1469. AllocatePasNames(aList.Classes,ParentName);
  1470. AllocatePasNames(aList.Interfaces,ParentName);
  1471. AllocatePasNames(aList.NameSpaces,ParentName);
  1472. AllocatePasNames(aList.Modules,ParentName);
  1473. end;
  1474. procedure TTypescriptToPas.EnsureUniqueNames(ML: TJSSourceElements);
  1475. begin
  1476. end;
  1477. procedure TTypescriptToPas.ProcessDefinitions;
  1478. begin
  1479. AllocatePasNames((FElements.A as TJSSourceElements));
  1480. end;
  1481. function TTypescriptToPas.ExportNode(aNode: TJSElementNode): Boolean;
  1482. begin
  1483. With aNode do
  1484. Result:=IsAmbient or IsExport;
  1485. end;
  1486. procedure TTypescriptToPas.CheckUnitName(SourceElements:TJSSourceElements);
  1487. Var
  1488. I : integer;
  1489. NN : String;
  1490. begin
  1491. NN:=OutputUnitName;
  1492. if (NN<>'') and (NN[1] in ['0'..'9']) then
  1493. begin
  1494. Dolog(SLogRenamingUnitCompile, [OutputUnitName, NN]);
  1495. NN:='_'+NN;
  1496. end;
  1497. For I:=0 to SourceElements.Functions.Count-1 do
  1498. if UTF8Encode((SourceElements.Functions[i].Node as TJSFunctionStatement).AFunction.Name)=OutputUnitName then
  1499. begin
  1500. NN:=NN+'_';
  1501. Dolog(SErrRenamingUnitConflict, [OutputUnitName, NN]);
  1502. end;
  1503. if OutputUnitName<>NN then
  1504. OutputUnitName:=NN;
  1505. end;
  1506. procedure TTypescriptToPas.Execute;
  1507. Var
  1508. SourceElements:TJSSourceElements;
  1509. Fwds : TStringList;
  1510. begin
  1511. FContext:=CreateContext;
  1512. try
  1513. PushNameScope;
  1514. Parse;
  1515. SourceElements:=FElements.A as TJSSourceElements;
  1516. Fwds:=TStringList.Create;
  1517. try
  1518. Context.PushScope(SourceElements,fwds);
  1519. ProcessDefinitions;
  1520. CheckUnitName(SourceElements);
  1521. FContext.TypesToMap;
  1522. if Verbose then
  1523. DoLog(SLogParsedNDefinitions, [FContext.FTypeMap.Count]);
  1524. finally
  1525. Context.PopScope(SourceElements,Fwds);
  1526. end;
  1527. if Assigned(TypeAliases) then
  1528. FContext.AddAliases(TypeAliases);
  1529. WritePascal;
  1530. if OutputFileName<>'' then
  1531. Source.SaveToFile(OutputFileName);
  1532. finally
  1533. PopNameScope;
  1534. FreeAndNil(FContext);
  1535. end;
  1536. end;
  1537. { ----------------------------------------------------------------------
  1538. Simple types
  1539. ----------------------------------------------------------------------}
  1540. Function TTypescriptToPas.GetArrayTypeAsString(aTypeDef : TJSArrayTypeDef; asPascal,asSubType : Boolean) : String;
  1541. begin
  1542. if Assigned(aTypeDef.BaseType.Data) then
  1543. Result:=TPasData(aTypeDef.BaseType.Data).PasName
  1544. else
  1545. Result:=GetTypeAsString(aTypeDef.BaseType,asPascal,True);
  1546. if coGenericArrays in Options then
  1547. Result:='TArray<'+Result+'>'
  1548. else
  1549. Result:='array of '+Result;
  1550. if (not asPascal) and AsSubType then
  1551. Result:='('+Result+')'
  1552. end;
  1553. Function TTypescriptToPas.GetTypeAsString(aType : TJSTypeDef; asPascal,asSubType : Boolean) : String;
  1554. begin
  1555. Result:='';
  1556. if aType is TJSTypeReference then
  1557. Result:=GetAliasTypeAsString(TJSTypeReference(aType),asPascal,asSubType)
  1558. else if aType is TJSUnionTypeDef then
  1559. Result:=GetUnionTypeAsString(TJSUnionTypeDef(aType),asPascal,asSubType)
  1560. else if aType is TJSIntersectionTypeDef then
  1561. Result:=GetIntersectionTypeAsString(TJSIntersectionTypeDef(aType),asPascal,asSubType)
  1562. else if aType is TJSArrayTypeDef then
  1563. Result:=GetArrayTypeAsString(TJSArrayTypeDef(aType),asPascal,asSubType)
  1564. else if aType is TJSEnumTypeDef then
  1565. Result:=GetEnumTypeAsString(TJSEnumTypeDef(aType),asPascal,asSubType)
  1566. else if aType is TJSTupleTypeDef then
  1567. Result:=GetTupleTypeAsString(TJSTupleTypeDef(aType),asPascal,True)
  1568. else if aType is TJSFixedValueReference then
  1569. Result:=GetFixedValueTypeAsString(TJSFixedValueReference(aType),asPascal,asSubType)
  1570. else
  1571. if asPascal then
  1572. if Assigned(aType.Data) then
  1573. Result:=TPasData(aType.Data).PasName;
  1574. end;
  1575. Function TTypescriptToPas.GetUnionTypeAsString(aTypeDef : TJSUnionTypeDef; asPascal,asSubType : Boolean) : String;
  1576. Var
  1577. I : Integer;
  1578. begin
  1579. Result:='';
  1580. For I:=0 to aTypeDef.TypeCount-1 do
  1581. begin
  1582. if Result<>'' then
  1583. Result:=Result+' | ';
  1584. Result:=Result+GetTypeAsString(aTypeDef.Types[I],asPascal,True);
  1585. end;
  1586. if AsSubType then
  1587. Result:='('+Result+')';
  1588. end;
  1589. function TTypescriptToPas.GetEnumTypeAsString(aTypeDef: TJSEnumTypeDef; asPascal, asSubType: Boolean): String;
  1590. Var
  1591. I : Integer;
  1592. N : String;
  1593. begin
  1594. Result:='';
  1595. For I:=0 to aTypeDef.NameCount-1 do
  1596. begin
  1597. if Result<>'' then
  1598. Result:=Result+', ';
  1599. N:=UTF8Encode(aTypeDef.Names[I]);
  1600. if IsKeyWord(N) then
  1601. N:='&'+N;
  1602. Result:=Result+N;
  1603. end;
  1604. Result:='('+Result+')';
  1605. if AsSubType then
  1606. Result:='('+Result+')';
  1607. end;
  1608. function TTypescriptToPas.GetFixedValueTypeAsString(aTypeDef: TJSFixedValueReference; asPascal, asSubType: Boolean): string;
  1609. begin
  1610. case aTypeDef.FixedValue.Value.ValueType of
  1611. jstUNDEFINED : Result:='jsValue';
  1612. jstNull : Result:='jsValue';
  1613. jstBoolean : Result:='Boolean';
  1614. jstNumber : Result:='Double';
  1615. jstString : Result:='string';
  1616. jstObject : Result:='TJSObject';
  1617. jstReference : Result:='jsValue';
  1618. jstCompletion : Result:='jsValue';
  1619. end;
  1620. end;
  1621. Function TTypescriptToPas.GetIntersectionTypeAsString(aTypeDef : TJSIntersectionTypeDef; asPascal,asSubType : Boolean) : String;
  1622. Var
  1623. I : Integer;
  1624. begin
  1625. Result:='';
  1626. For I:=0 to aTypeDef.TypeCount-1 do
  1627. begin
  1628. if Result<>'' then
  1629. Result:=Result+' & ';
  1630. Result:=Result+GetTypeAsString(aTypeDef.Types[I],asPascal,True);
  1631. end;
  1632. if AsSubType then
  1633. Result:='('+Result+')';
  1634. end;
  1635. Procedure TTypescriptToPas.WriteUnionTypeDef(const aPasName : string; const aOrgName : jsBase.TJSString; aTypeParams: TJSElementNodes;aTypeDef : TJSUnionTypeDef);
  1636. var
  1637. TN, gen, genparams, tcomment: String;
  1638. begin
  1639. TN:='jsvalue';
  1640. if aTypeDef.GetOnlyConstants=ocAllSameTypes then
  1641. begin
  1642. TN:=GetTypeAsString((aTypeDef.Values[0].Node as TJSFixedValueReference),True,False);
  1643. tcomment:=' // Restricted values';
  1644. end
  1645. else
  1646. tcomment:=' // '+GetTypeAsString(aTypeDef,False,False);
  1647. genparams:=GetGenericParams(aTypeParams);
  1648. if (genparams<>'') then
  1649. gen:='generic ';
  1650. AddLn('%s%s%s = %s;%s',[gen,aPasName,genparams,TN,tcomment]);
  1651. end;
  1652. function TTypescriptToPas.GetTupleTypeAsString(aTypeDef: TJSTupleTypeDef; asPascal,asSubType : Boolean) : String;
  1653. Var
  1654. N :TJSTypeReference;
  1655. elName : string;
  1656. begin
  1657. Result:='jsvalue';
  1658. if aTypeDef.Values.Count=0 then
  1659. exit;
  1660. if (Not aTypeDef.GetEqualTypes) or (coUntypedTuples in Options) then
  1661. begin
  1662. if coDynamicTuples in Options then
  1663. Result:='TJSValueDynArray'
  1664. else
  1665. Result:=Format('Array[0..%d] of JSValue',[aTypeDef.Values.Count-1]);
  1666. end
  1667. else if aTypeDef.Values[0].Node is TJSTypeReference then
  1668. begin
  1669. N:=aTypeDef.Values[0].Node as TJSTypeReference;
  1670. ElName:=GetTypeAsString(N,True,False);
  1671. if coDynamicTuples in Options then
  1672. Result:=Format('Array of %s',[ElName])
  1673. else
  1674. Result:=Format('Array[0..%d] of %s',[aTypeDef.Values.Count-1,elName]);
  1675. end
  1676. else
  1677. raise ETSToPas.CreateFmt(SErrUnsupportedTupleElementType, [aTypeDef.Values[0].Node.ClassName]);
  1678. end;
  1679. procedure TTypescriptToPas.WriteTupleTypeDef(const aPasName: string; const aOrgName: jsBase.TJSString;
  1680. aTypeParams: TJSElementNodes; aTypeDef: TJSTupleTypeDef);
  1681. var
  1682. TN, gen, genparams: String;
  1683. begin
  1684. genparams:=GetGenericParams(aTypeParams);
  1685. if (genparams<>'') then
  1686. gen:='generic ';
  1687. TN:=GetTupleTypeAsString(aTypeDef,True,False);
  1688. AddLn('%s%s%s = %s;',[gen,aPasName,genparams,TN]);
  1689. end;
  1690. Procedure TTypescriptToPas.WriteIntersectionTypeDef(const aPasName : string; const aOrgName : jsBase.TJSString; aTypeParams: TJSElementNodes;aTypeDef : TJSIntersectionTypeDef);
  1691. var
  1692. TN, gen, genparams: String;
  1693. begin
  1694. TN:='jsvalue';
  1695. genparams:=GetGenericParams(aTypeParams);
  1696. if (genparams<>'') then
  1697. gen:='generic ';
  1698. AddLn('%s%s%s = %s; // %s',[gen,aPasName,genparams,TN,GetTypeAsString(aTypeDef,False,false)]);
  1699. end;
  1700. Procedure TTypescriptToPas.WriteArrayTypeDef(const aPasName : string; const aOrgName : jsBase.TJSString; aTypeParams: TJSElementNodes;aTypeDef : TJSArrayTypeDef);
  1701. var
  1702. arr,gen, genparams: String;
  1703. begin
  1704. genparams:=GetGenericParams(aTypeParams);
  1705. if (genparams<>'') then
  1706. gen:='generic ';
  1707. arr:=GetArrayTypeAsString(aTypeDef,True,False);
  1708. AddLn('%s%s%s = %s;',[gen,aPasName,genparams,arr]);
  1709. end;
  1710. procedure TTypescriptToPas.WriteEnumTypeDef(const aPasName: string; const aOrgName: jsBase.TJSString; aTypeParams: TJSElementNodes;
  1711. aTypeDef: TJSEnumTypeDef);
  1712. var
  1713. arr,gen, genparams: String;
  1714. begin
  1715. genparams:=GetGenericParams(aTypeParams);
  1716. if (genparams<>'') then
  1717. gen:='generic ';
  1718. arr:=GetEnumTypeAsString(aTypeDef,True,False);
  1719. AddLn('%s%s%s = %s;',[gen,aPasName,genparams,arr]);
  1720. end;
  1721. Procedure TTypescriptToPas.WriteTypeDef(const aPasName : string; const aOrgName : jsBase.TJSString; aTypeParams: TJSElementNodes; aTypeDef : TJSTypeDef);
  1722. begin
  1723. if NameScopeHas(aPasName) then
  1724. begin
  1725. Comment(Format(SCommentIgnoringDuplicateType, [aPasName, UTF8Encode(aOrgName)]));
  1726. exit;
  1727. end;
  1728. AddToNameScope(aPasName,aOrgName);
  1729. If aTypeDef is TJSTypeReference then
  1730. WriteAliasTypeDef(aPasName,aOrgName,aTypeParams,TJSTypeReference(aTypeDef))
  1731. else if aTypeDef is TJSUnionTypeDef then
  1732. WriteUnionTypeDef(aPasName,aOrgName,aTypeParams,TJSUnionTypeDef(aTypeDef))
  1733. else if aTypeDef is TJSIntersectionTypeDef then
  1734. WriteIntersectionTypeDef(aPasName,aOrgName,aTypeParams,TJSIntersectionTypeDef(aTypeDef))
  1735. else if aTypeDef is TJSArrayTypeDef then
  1736. WriteArrayTypeDef(aPasName,aOrgName,aTypeParams,TJSArrayTypeDef(aTypeDef))
  1737. else if aTypeDef is TJSEnumTypeDef then
  1738. WriteEnumTypeDef(aPasName,aOrgName,aTypeParams,TJSEnumTypeDef(aTypeDef))
  1739. else if aTypeDef is TJSArrowFunctionTypeDef then
  1740. WriteFunctionTypeDef(aPasName,aOrgName,aTypeParams,TJSArrowFunctionTypeDef(aTypeDef).aFunction)
  1741. else if aTypeDef is TJSObjectTypeDef then
  1742. WriteObjectTypedef(aPasName,aOrgName,aTypeParams,TJSObjectTypeDef(aTypeDef))
  1743. else if aTypeDef is TJSTupleTypeDef then
  1744. WriteTupleTypedef(aPasName,aOrgName,aTypeParams,TJSTupleTypeDef(aTypeDef))
  1745. else
  1746. Comment(Format(SErrUnsupportedType, [aPasName, aOrgName, aTypeDef.ClassName]));
  1747. end;
  1748. function TTypescriptToPas.WriteIndirectTypeDefs(aParams: TJStypedParams): Integer;
  1749. Var
  1750. I : Integer;
  1751. aParam : TJSTypedParam;
  1752. FuncDef : TJSFuncDef;
  1753. PD : TPasData;
  1754. begin
  1755. // Writeln('WITD params');
  1756. Result:=0;
  1757. For I:=0 to aParams.Count-1 do
  1758. begin
  1759. aParam:=aParams[i];
  1760. if TypeNeedsTypeName(aParam.Node,True) then
  1761. begin
  1762. Inc(Result);
  1763. PD:=TPasData(aParam.Node.Data);
  1764. // Recurse
  1765. if aParam.Node is TJSArrowFunctionTypeDef then
  1766. begin
  1767. FuncDef:=(aParam.Node as TJSArrowFunctionTypeDef).aFunction;
  1768. Result:=Result+WriteIndirectTypeDefs(FuncDef.TypedParams);
  1769. if TypeNeedsTypeName(FuncDef.ResultType,True) then
  1770. begin
  1771. PD:=TPasData(aParam.Node.Data);
  1772. Inc(Result);
  1773. WriteTypeDef(PD.PasName,PD.OriginalName,nil, FuncDef.ResultType);
  1774. end
  1775. end
  1776. else if aParam.Node is TJSArrayTypeDef then
  1777. begin
  1778. if TypeNeedsTypeName(TJSArrayTypeDef(aParam.Node).BaseType,True,True) then
  1779. begin
  1780. PD:=TPasData(TJSArrayTypeDef(aParam.Node).BaseType.Data);
  1781. Inc(Result);
  1782. WriteTypeDef(PD.PasName,PD.OriginalName,nil, TJSArrayTypeDef(aParam.Node).BaseType);
  1783. end
  1784. end;
  1785. PD:=TPasData(aParam.Node.Data);
  1786. WriteTypeDef(PD.PasName,PD.OriginalName,nil,(aParam.Node as TJSTypeDef));
  1787. end;
  1788. end;
  1789. end;
  1790. function TTypescriptToPas.HasIndirectTypeDefs(aParams: TJStypedParams): Boolean;
  1791. Var
  1792. I : Integer;
  1793. aParam : TJSTypedParam;
  1794. begin
  1795. Result:=False;
  1796. I:=0;
  1797. While (Not Result) and (I<aParams.Count) do
  1798. begin
  1799. aParam:=aParams[i];
  1800. Result:=Assigned(aParam.Node) and Assigned(aParam.Node.Data);
  1801. Inc(I);
  1802. end;
  1803. end;
  1804. function TTypescriptToPas.HasIndirectTypeDefs(aElements: TJSElementNodes): Boolean;
  1805. var
  1806. EN : TJSElementNode;
  1807. FD : TJSFuncDef;
  1808. begin
  1809. Result:=False;
  1810. For EN in aElements do
  1811. if ExportNode(EN) then
  1812. begin
  1813. if (EN.Node is TJSFunctionStatement) then
  1814. begin
  1815. FD:=TJSFunctionStatement(EN.Node).AFunction;
  1816. Result:=HasIndirectTypeDefs(FD.TypedParams);
  1817. if Result then
  1818. Exit;
  1819. end;
  1820. if (EN.Node is TJSObjectTypeDef) then
  1821. begin
  1822. Result:=HasIndirectTypeDefs(TJSObjectTypeDef(EN.Node).Values);
  1823. if Result then
  1824. Exit;
  1825. end;
  1826. if (EN.Node is TJSVarDeclaration) then
  1827. begin
  1828. Result:=TJSVarDeclaration(EN.Node).Typed is TJSObjectTypeDef;
  1829. if Result then
  1830. Exit;
  1831. end;
  1832. end;
  1833. end;
  1834. function TTypescriptToPas.WriteIndirectTypeDefs(aEl : TJSElement): Integer;
  1835. Var
  1836. PD : TPasData;
  1837. begin
  1838. Result:=0;
  1839. if aEl is TJSArrowFunctionTypeDef then
  1840. Result:=WriteIndirectTypeDefs((aEl as TJSArrowFunctionTypeDef).aFunction)
  1841. else if aEl is TJSArrayTypeDef then
  1842. begin
  1843. Result:=WriteIndirectTypeDefs((aEl as TJSArrayTypeDef).BaseType);
  1844. PD:=TPasData((aEl as TJSArrayTypeDef).BaseType.Data);
  1845. if assigned(PD) then
  1846. WriteTypeDef(PD.PasName,PD.OriginalName,Nil,(aEl as TJSArrayTypeDef).BaseType);
  1847. end
  1848. else if aEl is TJSObjectTypeDef then
  1849. Result:=WriteIndirectTypeDefs((aEl as TJSObjectTypeDef).Values);
  1850. end;
  1851. function TTypescriptToPas.WriteIndirectTypeDefs(FD : TJSFuncDef): Integer;
  1852. var
  1853. PD : TPasData;
  1854. begin
  1855. // Writeln('WIDT Func : ',FD.Name);
  1856. Result:=WriteIndirectTypeDefs(FD.TypedParams);
  1857. if TypeNeedsTypeName(FD.ResultType,True,True) then
  1858. begin
  1859. WriteIndirectTypeDefs(FD.ResultType);
  1860. PD:=TPasData(FD.ResultType.Data);
  1861. if PD=Nil then
  1862. raise ETSToPas.CreateFmt(SErrNoNameAllocatedForFunctionResult, [FD.Name, FD.ResultType.Line, FD.ResultType.Column,
  1863. FD.ResultType.ClassName]);
  1864. WriteTypeDef(PD.PasName,PD.OriginalName,nil,FD.ResultType);
  1865. end;
  1866. end;
  1867. function TTypescriptToPas.WriteIndirectTypeDefs(aElements: TJSElementNodes): Integer;
  1868. var
  1869. EN : TJSElementNode;
  1870. FD : TJSFuncDef;
  1871. begin
  1872. // Writeln('WIDT elements: ');
  1873. Result:=0;
  1874. For EN in aElements do
  1875. begin
  1876. FD:=Nil;
  1877. if (EN.Node is TJSFunctionStatement) then
  1878. FD:=TJSFunctionStatement(EN.Node).AFunction
  1879. else if (EN.Node is TJSTypeDeclaration) and (TJSTypeDeclaration(EN.Node).TypeDef is TJSArrowFunctionTypeDef) then
  1880. FD:=TJSArrowFunctionTypeDef(TJSTypeDeclaration(En.Node).TypeDef).aFunction;
  1881. if Assigned(FD) then
  1882. Result:=Result+WriteIndirectTypeDefs(FD)
  1883. end;
  1884. WritePropertyTypeDefs(aElements,'');
  1885. end;
  1886. function TTypescriptToPas.WritePropertyTypeDefs(aElements: TJSElementNodes; const SectionName: String): Integer;
  1887. Var
  1888. P : TJSPropertyDeclaration;
  1889. aName : TJSString;
  1890. PD : TPasData;
  1891. EN : TJSElementNode;
  1892. TD : TJSTypeDef;
  1893. DidIndent : Boolean;
  1894. begin
  1895. Result:=0;
  1896. DidIndent:=False;
  1897. For EN in aElements do
  1898. begin
  1899. TD:=Nil;
  1900. aName:='';
  1901. if EN.Node is TJSPropertyDeclaration then
  1902. begin
  1903. P:=TJSPropertyDeclaration(EN.Node);
  1904. aName:=P.Name;
  1905. TD:=P.ElementType;
  1906. If not TypeNeedsTypeName(TD,True,True) then
  1907. TD:=Nil
  1908. end
  1909. else if EN.Node is TJSVarDeclaration then
  1910. begin
  1911. aName:=TJSVarDeclaration(EN.Node).Name;
  1912. TD:=TJSVarDeclaration(EN.Node).Typed;
  1913. if not (TD is TJSObjectTypeDef) then
  1914. TD:=nil;
  1915. end;
  1916. if Assigned(TD) then
  1917. begin
  1918. if (Result=0) and (SectionName<>'') then
  1919. begin
  1920. AddLn(SectionName);
  1921. Indent;
  1922. AddLn('Type');
  1923. Indent;
  1924. DidIndent:=True;
  1925. end;
  1926. PD:=TPasData(TD.Data);
  1927. if TD is TJSArrowFunctionTypeDef then
  1928. Result:=Result+WriteIndirectTypeDefs((TD as TJSArrowFunctionTypeDef).aFunction)
  1929. else if TD is TJSObjectTypeDef then
  1930. Result:=Result+WriteIndirectTypeDefs((TD as TJSObjectTypeDef).Values);
  1931. if PD=Nil then
  1932. raise ETSToPas.CreateFmt(SErrElementWithoutTypeName, [aName, TD.ClassName]);
  1933. WriteTypeDef(PD.PasName,PD.OriginalName,Nil,TD);
  1934. Inc(Result);
  1935. end;
  1936. end;
  1937. if DidIndent then
  1938. begin
  1939. Undent;
  1940. Undent;
  1941. end;
  1942. end;
  1943. function TTypescriptToPas.WriteMethodParameterDefs(aElements: TJSElementNodes; const SectionName: String): Integer;
  1944. var
  1945. EN : TJSElementNode;
  1946. FD : TJSFuncDef;
  1947. Didindent : Boolean;
  1948. begin
  1949. Result:=0;
  1950. DidIndent:=False;
  1951. For EN in aElements do
  1952. if EN.Node is TJSMethodDeclaration then
  1953. begin
  1954. FD:=TJSMethodDeclaration(EN.Node).FuncDef;
  1955. if (Result=0) and (SectionName<>'') then
  1956. begin
  1957. AddLn(SectionName);
  1958. Indent;
  1959. AddLn('Type');
  1960. Indent;
  1961. DidIndent:=True;
  1962. end;
  1963. WriteIndirectTypeDefs(FD);
  1964. end;
  1965. if DidIndent then
  1966. begin
  1967. Undent;
  1968. Undent;
  1969. end;
  1970. end;
  1971. Procedure TTypescriptToPas.WriteTypeDefs(Types: TJSElementNodes);
  1972. Var
  1973. I : Integer;
  1974. N : TJSElement;
  1975. Decl : TJSTypeDeclaration absolute N;
  1976. aName : String;
  1977. begin
  1978. EnsureSection(csType);
  1979. for I:=0 to Types.Count-1 do
  1980. if ExportNode(Types[i]) then
  1981. begin
  1982. N:=Types[I].Node;
  1983. // TJSEnumDeclaration is a descendent
  1984. if N is TJSTypeDeclaration then
  1985. begin
  1986. aName:=GetName(Decl);
  1987. WriteTypeDef(aName, Decl.Name, Decl.TypeParams, Decl.TypeDef);
  1988. end
  1989. end;
  1990. end;
  1991. function TTypescriptToPas.WritePrivateReadOnlyField(P : TJSPropertyDeclaration) : Boolean;
  1992. Var
  1993. FN : String;
  1994. begin
  1995. Result:=True;
  1996. FN:=StringReplace(GetName(P),'&','',[rfReplaceAll]);
  1997. AddLn('%s%s : %s; external name ''%s''; ',[FieldPrefix,FN,GetTypeName(P.ElementType),P.Name]);
  1998. end;
  1999. function TTypescriptToPas.WritePrivateReadOnlyField(M : TJSMethodDeclaration) : Boolean;
  2000. Var
  2001. FN : String;
  2002. begin
  2003. Result:=True;
  2004. FN:=StringReplace(GetName(M),'&','',[rfReplaceAll]);
  2005. AddLn('%s%s : %s; external name ''%s''; ',[FieldPrefix,FN,GetTypeName(M.FuncDef.ResultType),M.Name]);
  2006. end;
  2007. Function TTypescriptToPas.HasReadOnlyPropFields(aTypeDef : TJSObjectTypeDef) : Boolean;
  2008. Var
  2009. I : Integer;
  2010. aEl : TJSObjectTypeElementDef;
  2011. P : TJSPropertyDeclaration;
  2012. begin
  2013. Result:=False;
  2014. I:=0;
  2015. While (Not Result) and (I<aTypeDef.ElementCount) do
  2016. begin
  2017. aEl:=aTypeDef.Elements[i];
  2018. if aEl is TJSPropertyDeclaration then
  2019. begin
  2020. P:=TJSPropertyDeclaration(aTypeDef.Elements[i]);
  2021. Result:=P.IsReadOnly;
  2022. end
  2023. else if aEl is TJSMethodDeclaration then
  2024. Result:=TJSMethodDeclaration(aEl).IsGet and not aTypeDef.HasSetter(ael.Name);
  2025. Inc(I);
  2026. end;
  2027. end;
  2028. Function TTypescriptToPas.WriteReadOnlyPropFields(aTypeDef : TJSObjectTypeDef) : Integer;
  2029. Var
  2030. I : Integer;
  2031. aEl : TJSObjectTypeElementDef;
  2032. P : TJSPropertyDeclaration;
  2033. begin
  2034. Result:=0;
  2035. For I:=0 to aTypeDef.ElementCount-1 do
  2036. begin
  2037. aEl:=aTypeDef.Elements[i];
  2038. if aEl is TJSPropertyDeclaration then
  2039. begin
  2040. P:=TJSPropertyDeclaration(aTypeDef.Elements[i]);
  2041. if P.IsReadOnly then
  2042. WritePrivateReadonlyField(P);
  2043. end
  2044. else if aEl is TJSMethodDeclaration then
  2045. if TJSMethodDeclaration(aEl).IsGet and not aTypeDef.HasSetter(ael.Name) then
  2046. WritePrivateReadonlyField(TJSMethodDeclaration(aEl));
  2047. end;
  2048. end;
  2049. function TTypescriptToPas.WriteClassIndirectTypeDefs(aElements: TJSElementNodes; isClassLocal : Boolean) : Integer;
  2050. Var
  2051. Sect : String;
  2052. begin
  2053. Result:=0;
  2054. if Not IsClassLocal then
  2055. begin
  2056. Result:=WritePropertyTypeDefs(aElements);
  2057. Result:=Result+WriteMethodParameterDefs(aElements);
  2058. end
  2059. else
  2060. begin
  2061. Result:=WriteMethodParameterDefs(aElements,'Public');
  2062. if Result>0 then
  2063. Sect:=''
  2064. else
  2065. Sect:='Public';
  2066. Result:=Result+WritePropertyTypeDefs(aElements,Sect);
  2067. end;
  2068. end;
  2069. function TTypescriptToPas.WriteAmbientClassDef(const aPasName: String; aOrgName: TJSString; aTypeParams: TJSElementNodes;
  2070. aClass: TJSAmbientClassDeclarationArray): Boolean;
  2071. Type
  2072. TMembers = array of TJSSourceElements;
  2073. Procedure AddNameSpaceMembers(var AMembers : TMembers);
  2074. Var
  2075. I : Integer;
  2076. NS : TJSNameSpaceDeclaration;
  2077. begin
  2078. Result:=False;
  2079. I:=Context.CurrentScope.NameSpaces.Count-1;
  2080. While (I>=0) do
  2081. begin
  2082. NS:=TJSNameSpaceDeclaration(Context.CurrentScope.NameSpaces[i].Node);
  2083. If (aOrgName = NS.Name) then
  2084. aMembers:=Concat(aMembers,[NS.Members]);
  2085. Dec(I);
  2086. end;
  2087. end;
  2088. Var
  2089. aParentName : string;
  2090. aCount : Integer;
  2091. Members : TMembers;
  2092. M : TJSSourceElements;
  2093. C,C0 : TJSAmbientClassDeclaration;
  2094. begin
  2095. Result:=True;
  2096. C0:=aClass[0];
  2097. if C0.Extends is TJSTypeReference then
  2098. aParentName:=GetTypeName(C0.Extends)
  2099. else
  2100. aParentName:=DefaultClassParent;
  2101. Members:=[];
  2102. AddNameSpaceMembers(Members);
  2103. if not (coLocalArgumentTypes in Options) then
  2104. for C in aClass do
  2105. WriteClassIndirectTypeDefs(C.ClassDef.Values,False);
  2106. AddLn('%s = class external name ''%s'' (%s)',[aPasName,aOrgName,aParentName]);
  2107. if (coLocalArgumentTypes in Options) then
  2108. begin
  2109. For C in aClass do
  2110. aCount:=WriteClassIndirectTypeDefs(C.ClassDef.Values,True)
  2111. end
  2112. else
  2113. aCount:=0;
  2114. for M in Members do
  2115. begin
  2116. if aCount=0 then
  2117. begin
  2118. Addln('Public');
  2119. Indent;
  2120. Addln('Type');
  2121. end;
  2122. WriteSourceElements(M,aOrgName);
  2123. Undent;
  2124. Addln('Public');
  2125. end;
  2126. For C in aClass do
  2127. WriteObjectTypeMembers(aPasName,aOrgName,aTypeParams,C.ClassDef);
  2128. AddLn('end;');
  2129. AddLn('');
  2130. end;
  2131. function TTypescriptToPas.WriteClassDefs(aClasses: TJSElementNodes): Integer;
  2132. Function GetClasses(const aName : String) : TJSAmbientClassDeclarationArray;
  2133. Var
  2134. I,aCount : Integer;
  2135. N : TJSElement;
  2136. begin
  2137. aCount:=0;
  2138. Result:=[];
  2139. SetLength(Result,aClasses.Count);
  2140. For I:=0 to aClasses.Count-1 do
  2141. begin
  2142. N:=aClasses[I].Node;
  2143. if N is TJSAmbientClassDeclaration then
  2144. if aName=GetName(N) then
  2145. begin
  2146. Result[aCount]:=TJSAmbientClassDeclaration(N);
  2147. Inc(aCount);
  2148. end;
  2149. end;
  2150. SetLength(Result,aCount);
  2151. end;
  2152. Var
  2153. I : Integer;
  2154. N : TJSElement;
  2155. AmbientDecl : TJSAmbientClassDeclarationArray;
  2156. // ClassDecl : TJSClassDeclaration absolute N;
  2157. aName : String;
  2158. L : TStringList;
  2159. begin
  2160. Result:=0;
  2161. EnsureSection(csType);
  2162. L:=TStringList.Create;
  2163. try
  2164. L.Duplicates:=DupIgnore;
  2165. for I:=0 to aClasses.Count-1 do
  2166. if ExportNode(aClasses[i]) then
  2167. begin
  2168. N:=aClasses[I].Node;
  2169. // TJSEnumDeclaration is a descendent
  2170. if N is TJSAmbientClassDeclaration then
  2171. L.Add(GetName(N));
  2172. end;
  2173. For I:=0 to L.Count-1 do
  2174. begin
  2175. aName:=L[I];
  2176. AmbientDecl:=GetClasses(aName);
  2177. if Length(AmbientDecl)>0 then
  2178. begin
  2179. if Length(AmbientDecl)>1 then
  2180. DoLog(SLogFoldingClassDefinitions, [Length(AmbientDecl), aName]);
  2181. if WriteAmbientClassDef(aName, AmbientDecl[0].Name, AmbientDecl[0].TypeParams, AmbientDecl) then
  2182. Inc(Result);
  2183. end;
  2184. end;
  2185. finally
  2186. L.Free;
  2187. end;
  2188. end;
  2189. function TTypescriptToPas.WritePropertyDef(aProp: TJSPropertyDeclaration): Boolean;
  2190. Var
  2191. Def,TN,FN,aName : String;
  2192. begin
  2193. Result:=True;
  2194. FN:=GetName(aProp);
  2195. TN:=GetTypeName(aProp.ElementType);
  2196. if TN='record' then
  2197. TN:='TJSObject';
  2198. if SameText(FN,TN) then
  2199. FN:=FN+'_';
  2200. Def:=Format('%s : %s;',[FN,TN]);
  2201. aName:=UTF8Encode(aProp.Name);
  2202. if (FN<>aName) then
  2203. Def:=Def+Format('external name ''%s'';',[aName]);
  2204. AddLn(Def);
  2205. end;
  2206. function TTypescriptToPas.WriteReadonlyProperty(aProp: TJSPropertyDeclaration): Boolean;
  2207. Var
  2208. TN,N,PN : String;
  2209. begin
  2210. Result:=True;
  2211. N:=StringReplace(GetName(aProp),'&','',[rfReplaceAll]);
  2212. PN:=N;
  2213. TN:=GetTypeName(aProp.ElementType);
  2214. if SameText(PN,TN) then
  2215. PN:='_'+PN;
  2216. AddLn('Property %s : %s Read %s%s; ',[PN,TN,FieldPrefix,N]);
  2217. end;
  2218. Function TTypescriptToPas.WriteObjectMethods(aAccess : TAccessibility; aTypeDef: TJSObjectTypeDef) : Integer;
  2219. Var
  2220. L : TStringList;
  2221. I,aCount : Integer;
  2222. FN : String;
  2223. aDefs : Array of TJSFuncDef;
  2224. begin
  2225. Result:=0;
  2226. L:=TStringList.Create;
  2227. try
  2228. L.Sorted:=true;
  2229. L.Duplicates:=dupIgnore;
  2230. For I:=0 to aTypeDef.ElementCount-1 do
  2231. if (aTypeDef.Elements[I].Accessibility=aAccess) and
  2232. (aTypeDef.Elements[I] is TJSMethodDeclaration) then
  2233. L.Add(GetName(aTypeDef.Elements[I]));
  2234. For FN in L do
  2235. begin
  2236. aCount:=0;
  2237. aDefs:=[];
  2238. SetLength(aDefs,aTypeDef.ElementCount);
  2239. For I:=0 to aTypeDef.ElementCount-1 do
  2240. if (aTypeDef.Elements[I].Accessibility=aAccess) and
  2241. (aTypeDef.Elements[I] is TJSMethodDeclaration) and
  2242. (GetName(aTypeDef.Elements[I])=FN) then
  2243. begin
  2244. if TJSMethodDeclaration(aTypeDef.Elements[I]).FuncDef=nil then
  2245. DoLog(SLogIgnoringEmptyMethod)
  2246. else
  2247. begin
  2248. aDefs[aCount]:=TJSMethodDeclaration(aTypeDef.Elements[I]).FuncDef;
  2249. inc(aCount);
  2250. end;
  2251. end;
  2252. SetLength(aDefs,aCount);
  2253. I:=Length(aDefs);
  2254. WriteFunctionDefinition(FN,aDefs,False);
  2255. end;
  2256. finally
  2257. L.Free;
  2258. end;
  2259. end;
  2260. procedure TTypescriptToPas.WriteIndexSignature(aSign : TJSIndexSignatureDeclaration);
  2261. begin
  2262. If aSign=Nil then
  2263. exit;
  2264. end;
  2265. procedure TTypescriptToPas.WriteObjectTypeMembers(const aPasName: String; const aOrigName: jsBase.TJSString; aTypeParams: TJSElementNodes; aTypeDef: TJSObjectTypeDef);
  2266. Var
  2267. I : Integer;
  2268. EmitAccessibility : Boolean;
  2269. begin
  2270. EmitAccessibility:=Not (aTypeDef is TJSInterfaceDeclaration);
  2271. if HasReadOnlyPropFields(aTypeDef) or aTypeDef.HasAccessMembers(accPrivate) then
  2272. begin
  2273. if EmitAccessibility then
  2274. AddLn(GetAccessName(accPrivate));
  2275. Indent;
  2276. WriteReadOnlyPropFields(aTypeDef);
  2277. WriteObjectMethods(accPrivate,aTypeDef);
  2278. WriteProperties(accPrivate,aTypeDef.Values);
  2279. Undent;
  2280. end;
  2281. if aTypeDef.HasAccessMembers(accProtected) then
  2282. begin
  2283. if EmitAccessibility then
  2284. AddLn(GetAccessName(accProtected));
  2285. Indent;
  2286. WriteObjectMethods(accProtected,aTypeDef);
  2287. WriteProperties(accProtected,aTypeDef.Values);
  2288. Undent;
  2289. end;
  2290. if aTypeDef.HasAccessMembers(accPublic) then
  2291. begin
  2292. if EmitAccessibility then
  2293. AddLn(GetAccessName(accPublic));
  2294. Indent;
  2295. WriteObjectMethods(accPublic,aTypeDef);
  2296. WriteProperties(accPublic,aTypeDef.Values);
  2297. undent;
  2298. end;
  2299. if aTypeDef.HasAccessMembers(accDefault) then
  2300. begin
  2301. if EmitAccessibility then
  2302. AddLn(GetAccessName(accPublic));
  2303. Indent;
  2304. WriteObjectMethods(accDefault,aTypeDef);
  2305. WriteProperties(accDefault,aTypeDef.Values);
  2306. undent;
  2307. end;
  2308. For I:=0 to aTypeDef.ElementCount-1 do
  2309. if aTypeDef.Elements[I] is TJSIndexSignatureDeclaration then
  2310. begin
  2311. Indent;
  2312. WriteIndexSignature(aTypeDef.Elements[I] as TJSIndexSignatureDeclaration);
  2313. Undent;
  2314. end;
  2315. end;
  2316. procedure TTypescriptToPas.WriteObjectTypedef(const aPasName: String; const aOrigName: jsBase.TJSString;
  2317. aTypeParams: TJSElementNodes; aTypeDef: TJSObjectTypeDef);
  2318. Var
  2319. I : Integer;
  2320. aName : string;
  2321. begin
  2322. aName:='Object';
  2323. For I:=0 to aTypeDef.ElementCount-1 do
  2324. if (aTypeDef.Elements[I].Name='new') and (aTypeDef.Elements[I] is TJSMethodDeclaration) then
  2325. aName:=UTF8Encode(aOrigName);
  2326. AddLn('%s = class external name ''%s'' (TJSObject)',[aPasName,aName]);
  2327. WriteObjectTypeMembers(aPasName,aOrigName,aTypeParams,aTypeDef);
  2328. AddLn('end;');
  2329. AddLn('');
  2330. end;
  2331. { ----------------------------------------------------------------------
  2332. Functions
  2333. ----------------------------------------------------------------------}
  2334. function TTypescriptToPas.GetArguments(aList: TJSTypedParams; ForceBrackets: Boolean): String;
  2335. Var
  2336. E : TJSElementNode;
  2337. aParam : TJSTypedParam absolute E;
  2338. aType : TJSTypeDef;
  2339. Arg,aArgType : string;
  2340. begin
  2341. Result:='';
  2342. For E in aList do
  2343. begin
  2344. Arg:=GetName(aParam);
  2345. if Not Assigned(aParam.Type_) then
  2346. aArgType:='jsvalue'
  2347. else
  2348. begin
  2349. aType:=aParam.Type_ as TJSTypeDef;
  2350. aArgType:=GetTypeName(AType);
  2351. end;
  2352. Arg:=Arg+' : '+aArgType;
  2353. if Result<>'' then
  2354. Result:=Result+'; ';
  2355. Result:=Result+Arg;
  2356. end;
  2357. if (Result<>'') or ForceBrackets then
  2358. Result:='('+Result+')';
  2359. end;
  2360. Type
  2361. // A partial params list is a list which has been generated for a optional argument.
  2362. // This is how we distinguish lists that can be added to from lists that cannot be added to:
  2363. // Additional parameters can never be added to a partial list.
  2364. TJSPartialParams = Class(TJSTypedParams);
  2365. procedure TTypescriptToPas.AddUnionOverloads(aList: TFunctionOverLoadArgumentsList; const AName: TJSString; UT: TJSUnionTypeDef);
  2366. Var
  2367. L,L2 : TFunctionOverLoadArgumentsList;
  2368. I,J : Integer;
  2369. D : TJSTypedParams;
  2370. Dups : TStringList;
  2371. begin
  2372. L2:=Nil;
  2373. L:=Nil;
  2374. Dups:=TStringList.Create;
  2375. try
  2376. Dups.Sorted:=True;
  2377. Dups.Duplicates:=dupIgnore;
  2378. L:=TFunctionOverLoadArgumentsList.Create(False);
  2379. L2:=TFunctionOverLoadArgumentsList.Create(False);
  2380. // Collect non partial argument lists
  2381. for I:=0 to AList.Count-1 do
  2382. begin
  2383. D:=TJSTypedParams(alist[i]);
  2384. if Not (D is TJSPartialParams) then
  2385. L.AddOverload(D);
  2386. end;
  2387. // Collect unique pascal types. Note that this can reduce the list to 1 element...
  2388. For I:=0 to UT.TypeCount-1 do
  2389. Dups.AddObject(GetTypeName(UT.Types[I]),UT.Types[I]);
  2390. // First, clone list and add argument to cloned lists
  2391. For I:=1 to Dups.Count-1 do
  2392. begin
  2393. // Clone list
  2394. CloneNonPartialParameterList(L,L2,False);
  2395. // Add argument to cloned list
  2396. AddParameterToOverloads(L2,aName,Dups.Objects[i] as TJSTypeDef);
  2397. // Add overloads to original list
  2398. For J:=0 to L2.Count-1 do
  2399. aList.Add(L2[J]);
  2400. L2.Clear;
  2401. end;
  2402. // Add first Union to original list
  2403. AddParameterToOverloads(L,aName,Dups.Objects[0] as TJSTypeDef);
  2404. finally
  2405. Dups.Free;
  2406. L2.Free;
  2407. L.Free;
  2408. end;
  2409. end;
  2410. function TTypescriptToPas.CloneNonPartialParameterList(aList: TFunctionOverLoadArgumentsList; ADest: TFunctionOverLoadArgumentsList = Nil; AsPartial: Boolean = True): integer;
  2411. Var
  2412. I : Integer;
  2413. DL,CL : TJSTypedParams;
  2414. begin
  2415. Result:=0;
  2416. if ADest=Nil then
  2417. ADest:=aList;
  2418. I:=aList.Count-1;
  2419. While (I>=0) do
  2420. begin
  2421. DL:=TJSTypedParams(alist[i]);
  2422. if Not (DL is TJSPartialParams) then
  2423. begin
  2424. Inc(Result);
  2425. if AsPartial then
  2426. CL:=TJSPartialParams.CreateTransient
  2427. else
  2428. CL:=TJSTypedParams.CreateTransient;
  2429. CL.Assign(DL);
  2430. aDest.AddOverload(CL);
  2431. end;
  2432. Dec(I);
  2433. end;
  2434. end;
  2435. procedure TTypescriptToPas.AddParameterToOverloads(aList: TFunctionOverLoadArgumentsList; const AName : TJSString; ATypeDef : TJSTypeDef);
  2436. Var
  2437. I : Integer;
  2438. aParam : TJSTypedParam;
  2439. aParams : TJSTypedParams;
  2440. begin
  2441. For I:=0 to aList.Count-1 do
  2442. begin
  2443. aParams:=TJSTypedParams(alist[i]);
  2444. if Not (aParams is TJSPartialParams) then
  2445. begin
  2446. aParam:=aParams.Add as TJSTypedParam;
  2447. aParam.Name:=aName;
  2448. aParam.Node:=ATypeDef;
  2449. end;
  2450. end;
  2451. end;
  2452. procedure TTypescriptToPas.AddParameterToOverloads(aList: TFunctionOverLoadArgumentsList; const aParam: TJSTypedParam);
  2453. Var
  2454. I : Integer;
  2455. aClonedParam : TJSTypedParam;
  2456. aParams : TJSTypedParams;
  2457. begin
  2458. For I:=0 to aList.Count-1 do
  2459. begin
  2460. aParams:=TJSTypedParams(alist[i]);
  2461. if Not (aParams is TJSPartialParams) then
  2462. begin
  2463. aClonedParam:=aParams.Add as TJSTypedParam;
  2464. aClonedParam.Assign(aParam);
  2465. end;
  2466. end;
  2467. end;
  2468. procedure TTypescriptToPas.AddOverloadParams(aList: TFunctionOverLoadArgumentsList; adef: TJSFuncDef; aIdx: Integer);
  2469. Var
  2470. aParam : TJSTypedParam;
  2471. D : TJSTypeDef;
  2472. UT : TJSUnionTypeDef;
  2473. begin
  2474. if aIdx>=ADef.TypedParams.Count then
  2475. Exit;
  2476. aParam:=ADef.TypedParams[aIdx];
  2477. if aParam.IsOptional then
  2478. CloneNonPartialParameterList(aList);
  2479. // Add current to list.
  2480. D:=aParam.Node as TJSTypeDef;
  2481. UT:=Nil;
  2482. if coExpandUnionTypeArgs in Options then
  2483. UT:=CheckUnionTypeDefinition(D);
  2484. if UT=Nil then
  2485. AddParameterToOverloads(aList,aParam)
  2486. else
  2487. AddUnionOverLoads(aList,aParam.Name,UT);
  2488. AddOverloadParams(aList,aDef,aIdx+1);
  2489. end;
  2490. function TTypescriptToPas.GetOverloads(const aDefs: TJSFuncDefArray): TFunctionOverLoadArgumentsList;
  2491. Var
  2492. aDef : TJSFuncDef;
  2493. aFunc : TFunctionOverLoadArgumentsList;
  2494. I : Integer;
  2495. begin
  2496. Result:=TFunctionOverLoadArgumentsList.Create;
  2497. try
  2498. aFunc:=TFunctionOverLoadArgumentsList.Create(False);
  2499. try
  2500. For aDef in aDefs do
  2501. begin
  2502. aFunc.Clear;
  2503. aFunc.Add(TJSTypedParams.CreateTransient);
  2504. AddOverloadParams(aFunc,adef,0);
  2505. For I:=0 to aFunc.Count-1 do
  2506. Result.Add(aFunc[I]);
  2507. end;
  2508. finally
  2509. aFunc.Free;
  2510. end;
  2511. Result.RemoveDuplicates(Self.Context);
  2512. except
  2513. Result.Free;
  2514. Raise;
  2515. end;
  2516. end;
  2517. function TTypescriptToPas.WriteFunctionTypeDef(const aPasName: string; const aOrgName: jsBase.TJSString; aTypeParams: TJSElementNodes; aDef: TJSFuncDef): Boolean;
  2518. Var
  2519. FN,RT,Args : String;
  2520. begin
  2521. Result:=True;
  2522. if aPasName<>'' then
  2523. FN:=aPasName
  2524. else
  2525. FN:=GetName(aDef);
  2526. RT:=GetTypeName(aDef.ResultType,False);
  2527. if (RT='void') then
  2528. RT:='';
  2529. Args:=GetArguments(aDef.TypedParams,False);
  2530. if Args<>'' then
  2531. Args:=' '+Args;
  2532. if (RT='') then
  2533. AddLn('%s = Procedure%s;',[FN,Args])
  2534. else
  2535. AddLn('%s = Function%s: %s;',[FN,Args,RT])
  2536. end;
  2537. function TTypescriptToPas.WriteFunctionDefinition(const aName : String; const aDefs: TJSFuncDefArray; UseExternal : Boolean): Boolean;
  2538. Var
  2539. PN, FN,RT,Suff,Args : String;
  2540. Overloads : TFPObjectList;
  2541. I : Integer;
  2542. begin
  2543. Result:=True;
  2544. RT:='';
  2545. if (aDefs[0].IsConstructor) or (aName='&constructor') then
  2546. begin
  2547. PN:='New'
  2548. end
  2549. else
  2550. begin
  2551. PN:=aName;
  2552. FN:=UTF8Encode(aDefs[0].Name);
  2553. if (FN<>'') and ((FN<>StringReplace(aName,'&','',[rfReplaceAll])) or UseExternal) then
  2554. Suff:=Format('; external name ''%s''',[FN]);
  2555. if Assigned(aDefs[0].ResultType) then
  2556. RT:=GetTypeName(aDefs[0].ResultType,False);
  2557. if (RT='void') then
  2558. RT:='';
  2559. end;
  2560. Overloads:=GetOverloads(ADefs);
  2561. try
  2562. if Overloads.Count>1 then
  2563. Suff:=Suff+'; overload';
  2564. For I:=0 to Overloads.Count-1 do
  2565. begin
  2566. Args:=GetArguments(TJSTypedParams(Overloads[i]),False);
  2567. if (RT='') then
  2568. begin
  2569. if (aDefs[0].IsConstructor) then
  2570. AddLn('Constructor %s%s%s;',[PN,Args,Suff])
  2571. else
  2572. AddLn('Procedure %s%s%s;',[PN,Args,Suff]);
  2573. end
  2574. else
  2575. AddLn('Function %s%s: %s%s;',[PN,Args,RT,Suff])
  2576. end;
  2577. finally
  2578. Overloads.Free;
  2579. end;
  2580. end;
  2581. function TTypescriptToPas.WriteFunctionDefs(aElements: TJSElementNodes; UseExternal : Boolean): Integer;
  2582. Var
  2583. aList : TStringList;
  2584. EN : TJSElementNode;
  2585. FN : String;
  2586. aDefs : TJSFuncDefArray;
  2587. aCount : Integer;
  2588. begin
  2589. Result:=0;
  2590. aList:=TStringList.Create;
  2591. try
  2592. aList.Sorted:=True;
  2593. aList.Duplicates:=dupIgnore;
  2594. // Get Unique names
  2595. For EN in aElements do
  2596. if ExportNode(EN) then
  2597. aList.Add(GetName(EN.Node));
  2598. // Generate function definition for each unique name
  2599. For FN in aList do
  2600. begin
  2601. // Collect all function defs for this name
  2602. aDefs:=[];
  2603. aCount:=0;
  2604. SetLength(aDefs,aElements.Count);
  2605. For EN in aElements do
  2606. if ExportNode(EN) and (GetName(EN.Node)=FN) then
  2607. begin
  2608. if (EN.Node as TJSFunctionDeclarationStatement).AFunction = Nil then
  2609. DoLog(SLogIgnoringEmptyFunction)
  2610. else
  2611. begin
  2612. aDefs[aCount]:=(EN.Node as TJSFunctionDeclarationStatement).AFunction;
  2613. inc(aCount)
  2614. end
  2615. end;
  2616. SetLength(aDefs,aCount);
  2617. WriteFunctionDefinition(FN,aDefs, UseExternal);
  2618. Inc(Result);
  2619. end;
  2620. finally
  2621. aList.Free;
  2622. end;
  2623. end;
  2624. { ----------------------------------------------------------------------
  2625. Classes
  2626. ----------------------------------------------------------------------}
  2627. function TTypescriptToPas.WriteForwardClass(aName : string) : Boolean;
  2628. begin
  2629. Result:=FContext.CurrentForwards.IndexOf(aName)=-1;
  2630. if Result then
  2631. AddLn('%s = Class;',[aName])
  2632. else
  2633. DoLog(SLogIgnoreDoubleClassDefinition, [aName]);
  2634. end;
  2635. function TTypescriptToPas.WriteForwardClassDef(aIntf: TJSInterfaceDeclaration): Boolean;
  2636. Var
  2637. N : String;
  2638. begin
  2639. N:=GetName(aIntf);
  2640. if Context.CurrentForwards.indexOf(N)=-1 then
  2641. if (coInterfaceAsClass in Options) or (aIntf.HasProperties) then
  2642. AddLn('%s = Class;',[N])
  2643. else
  2644. AddLn('%s = Interface;',[N]);
  2645. Result:=True
  2646. end;
  2647. function TTypescriptToPas.WriteForwardClassDef(aObj: TJSTypeDeclaration): Boolean;
  2648. begin
  2649. Result:=WriteForwardClass(GetName(aObj));
  2650. end;
  2651. function TTypescriptToPas.WriteForwardClassDef(aClass: TJSClassDeclaration): Boolean;
  2652. begin
  2653. Result:=WriteForwardClass(GetName(aClass));
  2654. end;
  2655. function TTypescriptToPas.WriteForwardClassDef(aModule: TJSModuleDeclaration): Boolean;
  2656. begin
  2657. Result:=WriteForwardClass(GetName(aModule));
  2658. end;
  2659. function TTypescriptToPas.WriteForwardClassDef(aNamespace: TJSNameSpaceDeclaration): Boolean;
  2660. begin
  2661. Result:=WriteForwardClass(GetName(aNamespace));
  2662. end;
  2663. function TTypescriptToPas.WriteForwardClassDefs(aClassList: TJSElementNodes): Integer;
  2664. Procedure MaybeComment;
  2665. begin
  2666. if Result=0 then
  2667. Comment(SForwardClassDefinitions);
  2668. end;
  2669. Var
  2670. D : TJSElementNode;
  2671. begin
  2672. Result:=0;
  2673. For D in aClassList do
  2674. if (D.Node is TJSTypeDeclaration) and (TJSTypeDeclaration(D.Node).TypeDef is TJSObjectTypeDef) then
  2675. begin
  2676. MaybeComment;
  2677. if WriteForwardClassDef(TJSTypeDeclaration(D.Node)) then
  2678. Inc(Result);
  2679. end
  2680. else if D.Node is TJSClassDeclaration then
  2681. begin
  2682. MaybeComment;
  2683. if WriteForwardClassDef(D.Node as TJSClassDeclaration) then
  2684. Inc(Result);
  2685. end
  2686. else if (D.Node is TJSModuleDeclaration) then
  2687. begin
  2688. MaybeComment;
  2689. if WriteForwardClassDef(D.Node as TJSModuleDeclaration) then
  2690. Inc(Result);
  2691. end
  2692. else if (D.Node is TJSNameSpaceDeclaration)
  2693. and not (NamespaceExtendsClass(D.Node as TJSNamespaceDeclaration))
  2694. and not (NamespaceExtendsModule(D.Node as TJSNamespaceDeclaration))then
  2695. begin
  2696. MaybeComment;
  2697. if WriteForwardClassDef(D.Node as TJSNamespaceDeclaration) then
  2698. Inc(Result);
  2699. end
  2700. else if (D.Node is TJSInterfaceDeclaration) and not TJSInterfaceDeclaration(D.Node).IsFunctionDef then
  2701. begin
  2702. MaybeComment;
  2703. if WriteForwardClassDef(D.Node as TJSInterfaceDeclaration) then
  2704. Inc(Result);
  2705. end;
  2706. // Ignore other types
  2707. end;
  2708. { ----------------------------------------------------------------------
  2709. Namespaces
  2710. ----------------------------------------------------------------------}
  2711. function TTypescriptToPas.WriteNamespaceDef(aNameSpace: TJSNamespaceDeclaration): Boolean;
  2712. Var
  2713. aPasName,aName : String;
  2714. begin
  2715. Result:=True;
  2716. aPasName:=GetName(aNameSpace);
  2717. aName:=GetExternalMemberName(aNamespace.Name);
  2718. AddLn('');
  2719. AddLn(Format('%s = class external name ''%s'' (TJSObject)',[aPasName,aName]));
  2720. Addln('Public');
  2721. Indent;
  2722. PushSection();
  2723. WriteSourceElements(aNameSpace.Members,aNamespace.Name);
  2724. PopSection;
  2725. Undent;
  2726. AddLn('end;');
  2727. AddLn('');
  2728. end;
  2729. Function TTypescriptToPas.NamespaceExtendsClass(aNs : TJSNamespaceDeclaration) : Boolean;
  2730. begin
  2731. Result:=HaveClass(aNS.Name);
  2732. end;
  2733. function TTypescriptToPas.NamespaceExtendsModule(aNs: TJSNamespaceDeclaration): Boolean;
  2734. begin
  2735. Result:=HaveModule(aNS.Name);
  2736. end;
  2737. function TTypescriptToPas.HaveClass(const aName: TJSString): Boolean;
  2738. Var
  2739. I : Integer;
  2740. begin
  2741. Result:=False;
  2742. I:=Context.CurrentScope.Classes.Count-1;
  2743. While (Not Result) and (I>=0) do
  2744. begin
  2745. Result:=(aName) = TJSClassDeclaration(Context.CurrentScope.Classes[i].Node).Name;
  2746. Dec(I);
  2747. end;
  2748. end;
  2749. function TTypescriptToPas.HaveModule(const aName: TJSString): Boolean;
  2750. Var
  2751. I : Integer;
  2752. begin
  2753. Result:=False;
  2754. I:=Context.CurrentScope.Modules.Count-1;
  2755. While (Not Result) and (I>=0) do
  2756. begin
  2757. Result:=(aName) = TJSClassDeclaration(Context.CurrentScope.Modules[i].Node).Name;
  2758. Dec(I);
  2759. end;
  2760. end;
  2761. function TTypescriptToPas.WriteNamespaceDefs(aNameSpaces: TJSElementNodes): Integer;
  2762. Var
  2763. EN : TJSElementNode;
  2764. NSDef : TJSNamespaceDeclaration;
  2765. begin
  2766. Result:=0;
  2767. For EN in aNameSpaces do
  2768. begin
  2769. NSDef:=EN.Node as TJSNamespaceDeclaration;
  2770. if Not NamespaceExtendsClass(NSDef) then
  2771. begin
  2772. If Result=0 then
  2773. Comment('Namespaces');
  2774. WriteNameSpaceDef(NSDef);
  2775. end;
  2776. end;
  2777. end;
  2778. { ----------------------------------------------------------------------
  2779. Modules
  2780. ----------------------------------------------------------------------}
  2781. function TTypescriptToPas.WriteModuleDef(aModule: TJSModuleDeclaration): Boolean;
  2782. Var
  2783. aPasName,aName : String;
  2784. begin
  2785. Result:=True;
  2786. aPasName:=GetName(aModule);
  2787. aName:=GetExternalMemberName(aModule.Name);
  2788. AddLn('');
  2789. AddLn(Format('%s = class external name ''%s'' (TJSObject)',[aPasName,aName]));
  2790. Addln('Public');
  2791. Indent;
  2792. PushSection();
  2793. WriteSourceElements(aModule.Members,aModule.Name);
  2794. PopSection;
  2795. Undent;
  2796. AddLn('end;');
  2797. AddLn('');
  2798. end;
  2799. function TTypescriptToPas.WriteModuleDefs(aModules: TJSElementNodes): Integer;
  2800. Function ExtendsClass(aNs : TJSModuleDeclaration) : Boolean;
  2801. Var
  2802. I : Integer;
  2803. begin
  2804. Result:=False;
  2805. I:=Context.CurrentScope.Classes.Count-1;
  2806. While (Not Result) and (I>=0) do
  2807. begin
  2808. Result:=(aNS.Name) = TJSClassDeclaration(Context.CurrentScope.Classes[i].Node).Name;
  2809. Dec(I);
  2810. end;
  2811. end;
  2812. Var
  2813. EN : TJSElementNode;
  2814. NSDef : TJSModuleDeclaration;
  2815. begin
  2816. Result:=0;
  2817. For EN in aModules do
  2818. begin
  2819. NSDef:=EN.Node as TJSModuleDeclaration;
  2820. if Not ExtendsClass(NSDef) then
  2821. begin
  2822. If Result=0 then
  2823. Comment('Modules');
  2824. WriteModuleDef(NSDef);
  2825. end;
  2826. end;
  2827. end;
  2828. { ----------------------------------------------------------------------
  2829. Interfaces
  2830. ----------------------------------------------------------------------}
  2831. function TTypescriptToPas.WriteInterfaceDef(Intfs: TJSInterfaceDeclarationArray): Boolean;
  2832. Var
  2833. CN,Decl,Sect : String;
  2834. UseLocal, UseClass : Boolean;
  2835. aCount : Integer;
  2836. PD : TPasData;
  2837. Func : TJSFuncDef;
  2838. Intf0: TJSInterfaceDeclaration;
  2839. Inf: TJSInterfaceDeclaration;
  2840. begin
  2841. Intf0:=Intfs[0];
  2842. if Intf0.IsFunctionDef then
  2843. begin
  2844. PD:=TPasData(Intf0.Data);
  2845. Func:=intf0.FunctionDef;
  2846. WriteMethodParameterDefs(intf0.Values);
  2847. WriteFunctionTypeDef(PD.PasName,PD.OriginalName,Intf0.TypeParams,Func);
  2848. Exit;
  2849. end;
  2850. Result:=True;
  2851. UseClass:=False;
  2852. CN:=GetName(Intf0);
  2853. For Inf in Intfs do
  2854. useClass:=useClass or (coInterfaceAsClass in Options) or Inf.HasProperties;
  2855. UseLocal:=(coLocalArgumentTypes in Options) and UseClass;
  2856. if not UseLocal then
  2857. begin
  2858. for Inf in Intfs do
  2859. begin
  2860. WritePropertyTypeDefs(inf.Values);
  2861. WriteMethodParameterDefs(inf.Values);
  2862. end;
  2863. end;
  2864. if UseClass then
  2865. Decl:=Format('%s = class external name ''Object'' (TJSObject)',[CN])
  2866. else
  2867. Decl:=Format('%s = interface',[CN]);
  2868. AddLn(Decl);
  2869. if UseLocal then
  2870. begin
  2871. aCount:=0;
  2872. for Inf in Intfs do
  2873. begin
  2874. if (aCount>0) then
  2875. Sect:=''
  2876. else
  2877. Sect:='Public';
  2878. aCount:=WritePropertyTypeDefs(inf.Values,Sect);
  2879. if (aCount>0) then
  2880. Sect:=''
  2881. else
  2882. Sect:='Public';
  2883. WriteMethodParameterDefs(inf.Values,Sect);
  2884. end;
  2885. end;
  2886. Indent;
  2887. for inf in Intfs do
  2888. WriteObjectTypeMembers(CN,Inf.name,Inf.TypeParams,Inf);
  2889. Undent;
  2890. AddLn('end;');
  2891. AddLn('');
  2892. end;
  2893. function TTypescriptToPas.WriteInterfaceDefs(aList: TJSElementNodes): Integer;
  2894. Function GetInterfaces(aName : String) : TJSInterfaceDeclarationArray;
  2895. Var
  2896. I,aCount : Integer;
  2897. N : TJSElement;
  2898. begin
  2899. aCount:=0;
  2900. Result:=[];
  2901. SetLength(Result,aList.Count);
  2902. For I:=0 to aList.Count-1 do
  2903. begin
  2904. N:=aList[I].Node;
  2905. if N is TJSInterfaceDeclaration then
  2906. if aName=GetName(N) then
  2907. begin
  2908. Result[aCount]:=TJSInterfaceDeclaration(N);
  2909. Inc(aCount);
  2910. end;
  2911. end;
  2912. SetLength(Result,aCount);
  2913. end;
  2914. Var
  2915. I : Integer;
  2916. N : TJSElement;
  2917. IntfDecl : TJSInterfaceDeclarationArray;
  2918. aName : String;
  2919. L : TStringList;
  2920. begin
  2921. Result:=0;
  2922. EnsureSection(csType);
  2923. L:=TStringList.Create;
  2924. try
  2925. L.Duplicates:=DupIgnore;
  2926. for I:=0 to aList.Count-1 do
  2927. if ExportNode(aList[i]) then
  2928. begin
  2929. N:=aList[I].Node;
  2930. // TJSEnumDeclaration is a descendent
  2931. if N is TJSInterfaceDeclaration then
  2932. L.Add(GetName(N));
  2933. end;
  2934. For I:=0 to L.Count-1 do
  2935. begin
  2936. aName:=L[I];
  2937. IntfDecl:=GetInterfaces(aName);
  2938. if Length(IntfDecl)>0 then
  2939. begin
  2940. if Length(IntfDecl)>1 then
  2941. DoLog(SLogFoldingInterfaceDefinitions, [Length(IntfDecl), aName]);
  2942. if WriteInterfaceDef(IntfDecl) then
  2943. Inc(Result);
  2944. end;
  2945. end;
  2946. finally
  2947. L.Free;
  2948. end;
  2949. end;
  2950. end.