unit passrcutil; {$mode objfpc}{$H+} interface uses Classes, SysUtils, pscanner, pparser, pastree; Type { TPasSrcAnalysis } TPasSrcAnalysis = class(TComponent) private FFilename : string; FResolver : TBaseFileResolver; FScanner : TPascalScanner; FParser : TPasParser; FModule : TPasModule; FContainer : TPasTreeContainer; FStream: TStream; procedure SetFileName(AValue: string); Function ResourceStringCount(Section : TPasSection) : Integer; Protected Procedure FreeParser; Procedure CheckParser; Procedure Parse; procedure GetRecordFields(Rec: TPasrecordType; List: TStrings; const APrefix: String = ''); virtual; procedure GetClassMembers(AClass: TPasClassType; List: TStrings; AVisibilities : TPasMemberVisibilities; const APrefix: String = ''); virtual; procedure GetEnumValues(Enum: TPasEnumType; List: TStrings; const APrefix: String = ''); virtual; procedure GetIdentifiers(Section: TPasSection; List: TStrings; Recurse: Boolean);virtual; procedure GetUses(ASection: TPasSection; List: TStrings);virtual; Public Destructor Destroy; override; Procedure GetInterfaceUnits(List : TStrings); Procedure GetImplementationUnits(List : TStrings); Procedure GetUsedUnits(List : TStrings); Procedure GetInterfaceIdentifiers(List : TStrings; Recurse : Boolean = False); Procedure GetImplementationIdentifiers(List : TStrings; Recurse : Boolean = False); Procedure GetAllIdentifiers(List : TStrings; Recurse : Boolean = False); Function InterfaceHasResourcestrings : Boolean; Function ImplementationHasResourcestrings : Boolean; Function HasResourcestrings : Boolean; Property Stream : TStream Read FStream Write FStream; Published Property FileName : string Read FFilename Write SetFileName; end; implementation Type { TSrcContainer } TSrcContainer = Class(TPasTreeContainer) Public function CreateElement(AClass: TPTreeElement; const AName: String; AParent: TPasElement; AVisibility: TPasMemberVisibility; const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;overload; override; function FindElement(const AName: String): TPasElement; override; end; { TSrcContainer } function TSrcContainer.CreateElement(AClass: TPTreeElement; const AName: String; AParent: TPasElement; AVisibility: TPasMemberVisibility; const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement; begin Result:=AClass.Create(AName,AParent); Result.Visibility:=AVisibility; Result.SourceFilename:=ASourceFileName; Result.SourceLinenumber:=ASourceLineNumber; end; function TSrcContainer.FindElement(const AName: String): TPasElement; begin Result:=Nil; end; { TPasSrcAnalysis } procedure TPasSrcAnalysis.SetFileName(AValue: string); begin if FFilename=AValue then Exit; FFilename:=AValue; FreeParser; end; function TPasSrcAnalysis.ResourceStringCount(Section: TPasSection): Integer; begin Result:=0; If Assigned(Section) and Assigned(Section.ResStrings) then Result:=Section.ResStrings.Count;; end; procedure TPasSrcAnalysis.FreeParser; begin FreeAndNil(FParser); FreeAndNil(FScanner); FreeAndNil(FContainer); FreeAndNil(FResolver); FreeAndNil(FModule); end; procedure TPasSrcAnalysis.CheckParser; Var D : String; begin If (FParser<>Nil) then exit; Try If Assigned(Stream) then begin FResolver:=TStreamResolver.Create; TStreamResolver(Fresolver).AddStream(FileName,Stream); end else FResolver:=TFileResolver.Create; D:=ExtractFilePath(FileName); If (D='') then D:='.'; FResolver.BaseDirectory:=D; FResolver.AddIncludePath(D); FScanner:=TPascalScanner.Create(FResolver); FScanner.OpenFile(FileName); FContainer:=TSrcContainer.Create; FParser:=TPasParser.Create(FScanner,FResolver,FContainer); FScanner.AddDefine('FPC'); except FreeParser; Raise; end; end; procedure TPasSrcAnalysis.Parse; begin If FModule<>Nil then exit; CheckParser; FParser.ParseMain(FModule); end; procedure TPasSrcAnalysis.GetRecordFields(Rec: TPasrecordType; List: TStrings; const APrefix: String = ''); Var I : Integer; E : TPasElement; V : TPasVariant; begin For I:=0 to Rec.Members.Count-1 do begin E:=TPasElement(Rec.Members[I]); if E<>Nil then List.Add(APrefix+E.Name); end; If Assigned(Rec.Variants) then For I:=0 to Rec.Variants.Count-1 do begin V:=TPasVariant(Rec.Variants[I]); if (v<>Nil) and (V.members<>Nil) then GetRecordFields(V.Members,List,APrefix); end; end; procedure TPasSrcAnalysis.GetClassMembers(AClass: TPasClassType; List: TStrings; AVisibilities: TPasMemberVisibilities; const APrefix: String); Var I : Integer; E : TPasElement; V : TPasVariant; begin For I:=0 to AClass.Members.Count-1 do begin E:=TPasElement(AClass.Members[I]); if (E<>Nil) and ((AVisibilities=[]) or (E.Visibility in AVisibilities)) then List.Add(APrefix+E.Name); end; end; destructor TPasSrcAnalysis.Destroy; begin FreeParser; inherited Destroy; end; procedure TPasSrcAnalysis.GetUses(ASection : TPasSection; List: TStrings); Var I : Integer; begin If Assigned(ASection) and Assigned(ASection.UsesList) then For I:=0 to ASection.UsesList.Count-1 do List.Add(TPasElement(ASection.UsesList[i]).Name); end; procedure TPasSrcAnalysis.GetInterfaceUnits(List: TStrings); begin Parse; GetUses(Fmodule.InterfaceSection,List); end; procedure TPasSrcAnalysis.GetImplementationUnits(List: TStrings); begin Parse; GetUses(Fmodule.ImplementationSection,List); end; procedure TPasSrcAnalysis.GetUsedUnits(List: TStrings); begin Parse; GetUses(Fmodule.InterfaceSection,List); GetUses(Fmodule.ImplementationSection,List); end; procedure TPasSrcAnalysis.GetEnumValues(Enum : TPasEnumType;List : TStrings; Const APrefix : String = ''); Var I : Integer; E : TPasElement; begin For I:=0 to Enum.Values.Count-1 do begin E:=TPasElement(Enum.Values[I]); If (E<>Nil) then List.Add(APrefix+E.Name); end; end; procedure TPasSrcAnalysis.GetIdentifiers(Section : TPasSection; List: TStrings; Recurse : Boolean); Var I : Integer; E : TPasElement; begin if not (Assigned(Section) and Assigned(Section.Declarations)) then Exit; For I:=0 to Section.Declarations.Count-1 do begin E:=TPasElement(Section.Declarations[I]); If (E.Name<>'') then List.Add(E.Name); if Recurse then begin If E is TPasEnumType then GetEnumValues(TPasEnumType(E),List,E.Name+'.') else if E is TPasRecordType then GetRecordFields(TPasRecordType(E),List,E.Name+'.') else if E is TPasClassType then GetClassMembers(TPasClassType(E),List,[],E.Name+'.') end; end; end; procedure TPasSrcAnalysis.GetInterfaceIdentifiers(List: TStrings; Recurse : Boolean = False); begin Parse; GetIdentifiers(Fmodule.InterfaceSection,List,Recurse); end; procedure TPasSrcAnalysis.GetImplementationIdentifiers(List: TStrings; Recurse: Boolean); begin Parse; GetIdentifiers(Fmodule.ImplementationSection,List,Recurse); end; procedure TPasSrcAnalysis.GetAllIdentifiers(List: TStrings; Recurse: Boolean); begin Parse; GetIdentifiers(Fmodule.InterfaceSection,List,Recurse); GetIdentifiers(Fmodule.ImplementationSection,List,Recurse); end; function TPasSrcAnalysis.InterfaceHasResourcestrings: Boolean; begin Parse; Result:=ResourceStringCount(Fmodule.InterfaceSection)>0; end; function TPasSrcAnalysis.ImplementationHasResourcestrings: Boolean; begin Parse; Result:=ResourceStringCount(Fmodule.ImplementationSection)>0; end; function TPasSrcAnalysis.HasResourcestrings: Boolean; begin Parse; Result:=(ResourceStringCount(Fmodule.InterfaceSection)>0) or (ResourceStringCount(Fmodule.ImplementationSection)>0); end; end.