passrcutil.pp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. unit passrcutil;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, pscanner, pparser, pastree;
  6. Type
  7. { TPasSrcAnalysis }
  8. TPasSrcAnalysis = class(TComponent)
  9. private
  10. FFilename : string;
  11. FResolver : TBaseFileResolver;
  12. FScanner : TPascalScanner;
  13. FParser : TPasParser;
  14. FModule : TPasModule;
  15. FContainer : TPasTreeContainer;
  16. FStream: TStream;
  17. procedure SetFileName(AValue: string);
  18. Function ResourceStringCount(Section : TPasSection) : Integer;
  19. Protected
  20. Procedure FreeParser;
  21. Procedure CheckParser;
  22. Procedure Parse;
  23. procedure GetRecordFields(Rec: TPasrecordType; List: TStrings; const APrefix: String = ''); virtual;
  24. procedure GetClassMembers(AClass: TPasClassType; List: TStrings; AVisibilities : TPasMemberVisibilities; const APrefix: String = ''); virtual;
  25. procedure GetEnumValues(Enum: TPasEnumType; List: TStrings; const APrefix: String = ''); virtual;
  26. procedure GetIdentifiers(Section: TPasSection; List: TStrings; Recurse: Boolean);virtual;
  27. procedure GetUses(ASection: TPasSection; List: TStrings);virtual;
  28. Public
  29. Destructor Destroy; override;
  30. Procedure GetInterfaceUnits(List : TStrings);
  31. Procedure GetImplementationUnits(List : TStrings);
  32. Procedure GetUsedUnits(List : TStrings);
  33. Procedure GetInterfaceIdentifiers(List : TStrings; Recurse : Boolean = False);
  34. Procedure GetImplementationIdentifiers(List : TStrings; Recurse : Boolean = False);
  35. Procedure GetAllIdentifiers(List : TStrings; Recurse : Boolean = False);
  36. Function InterfaceHasResourcestrings : Boolean;
  37. Function ImplementationHasResourcestrings : Boolean;
  38. Function HasResourcestrings : Boolean;
  39. Property Stream : TStream Read FStream Write FStream;
  40. Published
  41. Property FileName : string Read FFilename Write SetFileName;
  42. end;
  43. implementation
  44. Type
  45. { TSrcContainer }
  46. TSrcContainer = Class(TPasTreeContainer)
  47. Public
  48. function CreateElement(AClass: TPTreeElement; const AName: String;
  49. AParent: TPasElement; AVisibility: TPasMemberVisibility;
  50. const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;overload; override;
  51. function FindElement(const AName: String): TPasElement; override;
  52. end;
  53. { TSrcContainer }
  54. function TSrcContainer.CreateElement(AClass: TPTreeElement;
  55. const AName: String; AParent: TPasElement; AVisibility: TPasMemberVisibility;
  56. const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;
  57. begin
  58. Result:=AClass.Create(AName,AParent);
  59. Result.Visibility:=AVisibility;
  60. Result.SourceFilename:=ASourceFileName;
  61. Result.SourceLinenumber:=ASourceLineNumber;
  62. end;
  63. function TSrcContainer.FindElement(const AName: String): TPasElement;
  64. begin
  65. if AName='' then ;
  66. Result:=Nil;
  67. end;
  68. { TPasSrcAnalysis }
  69. procedure TPasSrcAnalysis.SetFileName(AValue: string);
  70. begin
  71. if FFilename=AValue then Exit;
  72. FFilename:=AValue;
  73. FreeParser;
  74. end;
  75. function TPasSrcAnalysis.ResourceStringCount(Section: TPasSection): Integer;
  76. begin
  77. Result:=0;
  78. If Assigned(Section) and Assigned(Section.ResStrings) then
  79. Result:=Section.ResStrings.Count;;
  80. end;
  81. procedure TPasSrcAnalysis.FreeParser;
  82. begin
  83. FreeAndNil(FParser);
  84. FreeAndNil(FScanner);
  85. FreeAndNil(FContainer);
  86. FreeAndNil(FResolver);
  87. FreeAndNil(FModule);
  88. end;
  89. procedure TPasSrcAnalysis.CheckParser;
  90. Var
  91. D : String;
  92. begin
  93. If (FParser<>Nil) then
  94. exit;
  95. Try
  96. If Assigned(Stream) then
  97. begin
  98. FResolver:=TStreamResolver.Create;
  99. TStreamResolver(Fresolver).AddStream(FileName,Stream);
  100. end
  101. else
  102. FResolver:=TFileResolver.Create;
  103. D:=ExtractFilePath(FileName);
  104. If (D='') then
  105. D:='.';
  106. FResolver.ModuleDirectory:=D;
  107. FResolver.BaseDirectory:=D;
  108. FResolver.AddIncludePath(D); // still needed?
  109. FScanner:=TPascalScanner.Create(FResolver);
  110. FScanner.OpenFile(FileName);
  111. FContainer:=TSrcContainer.Create;
  112. FParser:=TPasParser.Create(FScanner,FResolver,FContainer);
  113. FScanner.AddDefine('FPC');
  114. except
  115. FreeParser;
  116. Raise;
  117. end;
  118. end;
  119. procedure TPasSrcAnalysis.Parse;
  120. begin
  121. If FModule<>Nil then exit;
  122. CheckParser;
  123. FParser.ParseMain(FModule);
  124. end;
  125. procedure TPasSrcAnalysis.GetRecordFields(Rec: TPasrecordType; List: TStrings;
  126. const APrefix: String = '');
  127. Var
  128. I : Integer;
  129. E : TPasElement;
  130. V : TPasVariant;
  131. begin
  132. For I:=0 to Rec.Members.Count-1 do
  133. begin
  134. E:=TPasElement(Rec.Members[I]);
  135. if E<>Nil then
  136. List.Add(APrefix+E.Name);
  137. end;
  138. If Assigned(Rec.Variants) then
  139. For I:=0 to Rec.Variants.Count-1 do
  140. begin
  141. V:=TPasVariant(Rec.Variants[I]);
  142. if (v<>Nil) and (V.members<>Nil) then
  143. GetRecordFields(V.Members,List,APrefix);
  144. end;
  145. end;
  146. procedure TPasSrcAnalysis.GetClassMembers(AClass: TPasClassType; List: TStrings;
  147. AVisibilities: TPasMemberVisibilities; const APrefix: String);
  148. Var
  149. I : Integer;
  150. E : TPasElement;
  151. begin
  152. For I:=0 to AClass.Members.Count-1 do
  153. begin
  154. E:=TPasElement(AClass.Members[I]);
  155. if (E<>Nil) and ((AVisibilities=[]) or (E.Visibility in AVisibilities)) then
  156. List.Add(APrefix+E.Name);
  157. end;
  158. end;
  159. destructor TPasSrcAnalysis.Destroy;
  160. begin
  161. FreeParser;
  162. inherited Destroy;
  163. end;
  164. procedure TPasSrcAnalysis.GetUses(ASection : TPasSection; List: TStrings);
  165. Var
  166. I : Integer;
  167. begin
  168. If not Assigned(ASection) then exit;
  169. if ASection.UsesList.Count=length(ASection.UsesClause) then
  170. For I:=0 to length(ASection.UsesClause)-1 do
  171. List.Add(ASection.UsesClause[i].Name)
  172. else
  173. For I:=0 to ASection.UsesList.Count-1 do
  174. List.Add(TPasElement(ASection.UsesList[i]).Name);
  175. end;
  176. procedure TPasSrcAnalysis.GetInterfaceUnits(List: TStrings);
  177. begin
  178. Parse;
  179. GetUses(Fmodule.InterfaceSection,List);
  180. end;
  181. procedure TPasSrcAnalysis.GetImplementationUnits(List: TStrings);
  182. begin
  183. Parse;
  184. GetUses(Fmodule.ImplementationSection,List);
  185. end;
  186. procedure TPasSrcAnalysis.GetUsedUnits(List: TStrings);
  187. begin
  188. Parse;
  189. GetUses(Fmodule.InterfaceSection,List);
  190. GetUses(Fmodule.ImplementationSection,List);
  191. end;
  192. procedure TPasSrcAnalysis.GetEnumValues(Enum : TPasEnumType;List : TStrings; Const APrefix : String = '');
  193. Var
  194. I : Integer;
  195. E : TPasElement;
  196. begin
  197. For I:=0 to Enum.Values.Count-1 do
  198. begin
  199. E:=TPasElement(Enum.Values[I]);
  200. If (E<>Nil) then
  201. List.Add(APrefix+E.Name);
  202. end;
  203. end;
  204. procedure TPasSrcAnalysis.GetIdentifiers(Section : TPasSection; List: TStrings; Recurse : Boolean);
  205. Var
  206. I : Integer;
  207. E : TPasElement;
  208. begin
  209. if not (Assigned(Section) and Assigned(Section.Declarations)) then
  210. Exit;
  211. For I:=0 to Section.Declarations.Count-1 do
  212. begin
  213. E:=TPasElement(Section.Declarations[I]);
  214. If (E.Name<>'') then
  215. List.Add(E.Name);
  216. if Recurse then
  217. begin
  218. If E is TPasEnumType then
  219. GetEnumValues(TPasEnumType(E),List,E.Name+'.')
  220. else if E is TPasRecordType then
  221. GetRecordFields(TPasRecordType(E),List,E.Name+'.')
  222. else if E is TPasClassType then
  223. GetClassMembers(TPasClassType(E),List,[],E.Name+'.')
  224. end;
  225. end;
  226. end;
  227. procedure TPasSrcAnalysis.GetInterfaceIdentifiers(List: TStrings; Recurse : Boolean = False);
  228. begin
  229. Parse;
  230. GetIdentifiers(Fmodule.InterfaceSection,List,Recurse);
  231. end;
  232. procedure TPasSrcAnalysis.GetImplementationIdentifiers(List: TStrings;
  233. Recurse: Boolean);
  234. begin
  235. Parse;
  236. GetIdentifiers(Fmodule.ImplementationSection,List,Recurse);
  237. end;
  238. procedure TPasSrcAnalysis.GetAllIdentifiers(List: TStrings; Recurse: Boolean);
  239. begin
  240. Parse;
  241. GetIdentifiers(Fmodule.InterfaceSection,List,Recurse);
  242. GetIdentifiers(Fmodule.ImplementationSection,List,Recurse);
  243. end;
  244. function TPasSrcAnalysis.InterfaceHasResourcestrings: Boolean;
  245. begin
  246. Parse;
  247. Result:=ResourceStringCount(Fmodule.InterfaceSection)>0;
  248. end;
  249. function TPasSrcAnalysis.ImplementationHasResourcestrings: Boolean;
  250. begin
  251. Parse;
  252. Result:=ResourceStringCount(Fmodule.ImplementationSection)>0;
  253. end;
  254. function TPasSrcAnalysis.HasResourcestrings: Boolean;
  255. begin
  256. Parse;
  257. Result:=(ResourceStringCount(Fmodule.InterfaceSection)>0)
  258. or (ResourceStringCount(Fmodule.ImplementationSection)>0);
  259. end;
  260. end.