dts2pas.pp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. { *********************************************************************
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 2021 Michael Van Canneyt.
  4. Typescript declaration module conversion to pascal program.
  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. program dts2pas;
  12. {$mode objfpc}{$H+}
  13. {AllowWriteln}
  14. uses
  15. TypInfo,Classes, SysUtils, StrUtils, CustApp, pascodegen, tstopas;
  16. Const
  17. DefaultOptions = [coInterfaceAsClass];
  18. type
  19. { TParseTSApplication }
  20. TParseTSApplication = class(TCustomApplication)
  21. private
  22. FVerbose,
  23. FWeb : Boolean;
  24. FLinks,
  25. FUnits,
  26. FAliases : TStringArray;
  27. FOptions : TConversionOptions;
  28. procedure AddAliases(Converter: TTypescriptToPas; aAlias: String);
  29. procedure AddWebAliases(S: Tstrings);
  30. procedure AddJSAliases(S: Tstrings);
  31. procedure DoLog(Sender: TObject; LogType: TCodegenLogType; const Msg: String);
  32. function GetOptions(aOptions: String): TConversionOptions;
  33. function ParseFile(const aInputFileName, aOutputFileName, aUnitName: string): Boolean;
  34. protected
  35. procedure DoRun; override;
  36. public
  37. constructor Create(TheOwner: TComponent); override;
  38. destructor Destroy; override;
  39. procedure Usage(Msg : string); virtual;
  40. end;
  41. { TParseTSApplication }
  42. function TParseTSApplication.GetOptions(aOptions : String) : TConversionOptions;
  43. Var
  44. T : TConversionOption;
  45. S : TStringArray;
  46. N : String;
  47. begin
  48. Result:=[];
  49. S:=SplitString(aOptions,', ');
  50. For T in TConversionOption do
  51. begin
  52. N:=GetEnumName(TypeInfo(TConversionOption),Ord(T));
  53. if IndexText(N,S)<>-1 then
  54. Include(Result,T);
  55. end;
  56. end;
  57. procedure TParseTSApplication.DoRun;
  58. var
  59. ErrorMsg: String;
  60. aUnitName,InputFile,OutputFile : String;
  61. begin
  62. Terminate;
  63. ErrorMsg:=CheckOptions('hi:o:a:wx:u:vl:s:', ['help','input:','output:','alias:','web','extra-units:','unitname:','verbose','link:','setting']);
  64. if (ErrorMsg<>'') or HasOption('h','help') then
  65. begin
  66. Usage(ErrorMsg);
  67. Exit;
  68. end;
  69. InputFile:=GetOptionValue('i','input');
  70. OutputFile:=GetOptionValue('o','output');
  71. FAliases:=GetOptionValues('a','alias');
  72. FLinks:=GetOptionValues('l','link');
  73. FUnits:=GetOptionValues('x','extra-units');
  74. FWeb:=HasOption('w','web');
  75. FVerbose:=HasOption('v','verbose');
  76. If OutputFile='' then
  77. if InputFile.EndsWith('d.ts') then
  78. OutputFile:=ChangeFileExt(ChangeFileExt(InputFile,''),'.pp')
  79. else
  80. OutputFile:=ChangeFileExt(InputFile,'.pp');
  81. if HasOption('s','setting') then
  82. FOptions:=GetOptions(GetOptionValue('s','setting'));
  83. aUnitName:=GetOptionValue('u','unitname');
  84. if aUnitName='' then
  85. aUnitName:=ChangeFileExt(ExtractFileName(outputFile),'');
  86. if not ParseFile(InputFIle,OutputFile,aUnitName) then
  87. ExitCode:=1;
  88. end;
  89. procedure TParseTSApplication.AddAliases(Converter : TTypescriptToPas; aAlias : String);
  90. Var
  91. aList : TStringList;
  92. S : String;
  93. begin
  94. if (aAlias='') then
  95. exit;
  96. if aAlias[1]='@' then
  97. begin
  98. AList:=TStringList.Create;
  99. try
  100. aList.LoadFromFile(Copy(aAlias,2,Length(aAlias)-1));
  101. Converter.TypeAliases.AddStrings(AList);
  102. finally
  103. AList.Free;
  104. end;
  105. end
  106. else
  107. For S in SplitString(aAlias,',;') do
  108. if Pos('=',S)<>0 then
  109. Converter.TypeAliases.Add(S);
  110. end;
  111. Function TParseTSApplication.ParseFile(const aInputFileName,aOutputFileName,aUnitName : string) : Boolean;
  112. Var
  113. Converter : TTypescriptToPas;
  114. A, S,U,U1,U2 : String;
  115. L : TStringArray;
  116. begin
  117. Result:=False;
  118. try
  119. Converter:=TTypescriptToPas.Create(Self);
  120. try
  121. AddJSAliases(Converter.TypeAliases);
  122. For A in FAliases do
  123. AddAliases(Converter,A);
  124. if FWeb then
  125. begin
  126. AddWebAliases(Converter.TypeAliases);
  127. Funits:=Concat(Funits, [ 'web' ]);
  128. end;
  129. U:='';
  130. For S in FUnits do
  131. begin
  132. L:=SplitString(S,',');
  133. For U1 in L do
  134. begin
  135. U2:=Trim(U1);
  136. if U2<>'' then
  137. begin
  138. if U<>'' then
  139. U:=U+', ';
  140. U:=U+U2;
  141. end;
  142. end;
  143. end;
  144. For S in Flinks do
  145. Converter.LinkStatements.Add(S);
  146. Converter.Verbose:=FVerbose;
  147. Converter.Options:=FOptions;
  148. Converter.ExtraUnits:=U;
  149. Converter.InputFileName:=aInputFileName;
  150. Converter.OutputFileName:=aOutputFileName;
  151. Converter.OutputUnitName:=aUnitName;
  152. Converter.Execute;
  153. Converter.OnLog:=@DoLog;
  154. Result:=True;
  155. finally
  156. Converter.Free;
  157. end;
  158. except
  159. on E : Exception do
  160. Writeln('Conversion error ',E.ClassName,' : ',E.Message);
  161. end;
  162. end;
  163. constructor TParseTSApplication.Create(TheOwner: TComponent);
  164. begin
  165. inherited Create(TheOwner);
  166. StopOnException:=True;
  167. FOptions:=DefaultOptions;
  168. end;
  169. destructor TParseTSApplication.Destroy;
  170. begin
  171. inherited Destroy;
  172. end;
  173. procedure TParseTSApplication.AddWebAliases(S : Tstrings);
  174. begin
  175. With S do
  176. begin
  177. {$i web.inc}
  178. end;
  179. end;
  180. procedure TParseTSApplication.AddJSAliases(S: Tstrings);
  181. begin
  182. With S do
  183. begin
  184. Add('Object=TJSObject');
  185. Add('Function=TJSFunction');
  186. Add('RegExp=TJSRegexp');
  187. Add('Promise=TJSPromise');
  188. Add('Date=TJSDate');
  189. Add('Array=TJSArray');
  190. Add('Iterator=TJSIterator');
  191. Add('IteratorResult=TJSIteratorResult');
  192. Add('AsyncIterator=TJSAsyncIterator');
  193. Add('ArrayBuffer=TJSArrayBuffer');
  194. Add('Set=TJSSet');
  195. Add('Map=TJSMap');
  196. Add('BufferSource=TJSBufferSource');
  197. Add('DataView=TJSDataView');
  198. Add('Int8Array=TJSInt8Array');
  199. Add('Int8ClampedArray=TJSInt8ClampedArray');
  200. Add('Int16Array=TJSInt16Array');
  201. Add('Int32Array=TJSInt32Array');
  202. Add('Uint8Array=TJSUInt8Array');
  203. Add('Uint8ClampedArray=TJSUInt8ClampedArray');
  204. Add('Uint16Array=TJSUInt16Array');
  205. Add('Uint32Array=TJSUInt32Array');
  206. Add('Float32Array=TJSFloat32Array');
  207. Add('Float64Array=TJSFloat64Array');
  208. Add('JSON=TJSJSON');
  209. Add('TextDecoder=TJSTextDecoder');
  210. Add('TextEncoder=TJSTextEncoder');
  211. Add('SyntaxError=TJSSyntaxError');
  212. Add('Error=TJSError');
  213. end;
  214. end;
  215. procedure TParseTSApplication.DoLog(Sender: TObject; LogType: TCodegenLogType; const Msg: String);
  216. begin
  217. Writeln('[',LogType,'] : ',Msg);
  218. end;
  219. procedure TParseTSApplication.Usage(Msg: string);
  220. Var
  221. S : String;
  222. CO : TConversionOption;
  223. begin
  224. if Msg<>'' then
  225. Writeln('Error : ',Msg);
  226. writeln('Usage: ', ExeName, ' [options]');
  227. Writeln('Where options is one or mote of:');
  228. Writeln('-a --alias=ALIAS Define type aliases (option can be speficied multiple times)');
  229. Writeln(' where ALIAS is one of');
  230. Writeln(' a comma-separated list of Alias=TypeName values');
  231. Writeln(' a @FILE : list is read from FILENAME, one line per alias');
  232. Writeln('-h --help Display this help text');
  233. Writeln('-i --input=FILENAME Parse .d.ts file FILENAME');
  234. Writeln('-l --link=FILENAME add {$linklib FILENAME} statement. (option can be specified multiple times)');
  235. Writeln('-o --output=FILENAME Output unit in file FILENAME');
  236. Writeln('-s --setting=SETTINGS Set options. SETTINGS is a comma-separated list of the following names:');
  237. for CO in TConversionOption do
  238. begin
  239. S:=GetEnumName(TypeInfo(TConversionOption),Ord(CO));
  240. if CO in DefaultOptions then S:=S+' (*)';
  241. Writeln(' ',S);
  242. end;
  243. Writeln(' Names marked with (*) are set in the default.');
  244. Writeln('-u --unit=NAME Set output unitname');
  245. Writeln('-w --web Add web unit to uses, define type aliases for web unit');
  246. Writeln('-x --extra-units=UNITLIST Add units (comma-separated list of unit names) to uses clause.');
  247. Writeln(' This option can be specified multiple times.');
  248. end;
  249. var
  250. Application: TParseTSApplication;
  251. begin
  252. Application:=TParseTSApplication.Create(nil);
  253. Application.Title:='My Application';
  254. Application.Run;
  255. Application.Free;
  256. end.