- Recompilación en Delphi10 de todos los paquetes de RO para generar las DCU's en Lib\D10 - Recompilación en Delphi10 de todos los paquetes de DA para generar las DCU's en Lib\D10 git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.RemObjects@9 b6239004-a887-0f4b-9937-50029ccdca16
570 lines
18 KiB
ObjectPascal
570 lines
18 KiB
ObjectPascal
unit uRODLSplitableConverter;
|
|
|
|
{----------------------------------------------------------------------------}
|
|
{ RemObjects SDK Library - CodeGen2 }
|
|
{ }
|
|
{ compiler: Delphi 5 and up, Kylix 2 and up }
|
|
{ platform: Win32, Linux }
|
|
{ }
|
|
{ (c)opyright RemObjects Software. all rights reserved. }
|
|
{ }
|
|
{ Using this code requires a valid license of the RemObjects SDK }
|
|
{ which can be obtained at http://www.remobjects.com. }
|
|
{----------------------------------------------------------------------------}
|
|
|
|
{$IFDEF LINUX}
|
|
{$I ../RemObjects.inc}
|
|
{$ELSE}
|
|
{$I ..\RemObjects.inc}
|
|
{$ENDIF LINUX}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, IniFiles, Contnrs, uRODL, uROClasses, uRODLLineStream, uRODLTemplateBasedConverter;
|
|
|
|
type
|
|
TRODLSplitableConverterFileList = class;
|
|
|
|
TRODLSplitableConverter = class (TRODLTemplateBasedConverter)
|
|
private
|
|
FTargetEntities: TStringList;
|
|
FOutputDir: string;
|
|
protected
|
|
FWrapperTemplateName: string;
|
|
FSplit: Boolean;
|
|
FFiles: TRODLSplitableConverterFileList;
|
|
|
|
procedure ProcessTemplate(const aLibrary: TRODLLibrary; template: TLineStream); override;
|
|
procedure SetupFiles(const aLibrary: TRODLLibrary); virtual; abstract;
|
|
procedure WriteWrapper(TypesList: TStringList; UsesList: TStringList); virtual;
|
|
function GetSplitFilesSuffix: string; virtual; abstract;
|
|
procedure AddEntityTypes(Types: {$IFDEF FPC}TStringList{$ELSE}THashedStringList{$ENDIF}; const AEntity: TRODLEntity; const unitName: string); virtual;
|
|
procedure ResolveRequiredUnits;
|
|
public
|
|
constructor Create(const aLibrary: TRODLLibrary; const aTemplateFileName: string; const aUnitName: string;
|
|
const ASplit: Boolean = False; const AOutputDir: string = '';
|
|
const AWrapperTemplateName: string = ''; const aTargetEntities: string = ''); reintroduce; virtual;
|
|
destructor Destroy; override;
|
|
|
|
property Split: Boolean read FSplit;
|
|
property SplitFilesSuffix: string read GetSplitFilesSuffix;
|
|
property OutputDir: string read FOutputDir;
|
|
end;
|
|
|
|
TRODLSplitableConverterFile = class
|
|
private
|
|
FEnums: TObjectList;
|
|
FArrays: TObjectList;
|
|
FStructs: TObjectList;
|
|
FEventSinks: TObjectList;
|
|
FExceptions: TObjectList;
|
|
FUnitName: string;
|
|
FServices: TObjectList;
|
|
FLibrary: TRODLLibrary;
|
|
FActiveList: TObjectList;
|
|
FLibraryList: IROStrings;
|
|
FConverter: TRODLSplitableConverter;
|
|
FRequiredUnits: TStringList;
|
|
function GetServices: TObjectList;
|
|
function GetUnitName: string;
|
|
function GetExceptions: TObjectList;
|
|
function GetEventSinks: TObjectList;
|
|
function GetStructs: TObjectList;
|
|
function GetArrays: TObjectList;
|
|
function GetEnums: TObjectList;
|
|
procedure SetupLists;
|
|
public
|
|
constructor Create(const aLibrary: TRODLLibrary; const aConverter: TRODLSplitableConverter);
|
|
destructor Destroy; override;
|
|
|
|
function GetActiveList: TObjectList;
|
|
function GetLibraryList: IROStrings;
|
|
|
|
property Services: TObjectList read GetServices;
|
|
property Enums: TObjectList read GetEnums;
|
|
property Arrays: TObjectList read GetArrays;
|
|
property Structs: TObjectList read GetStructs;
|
|
property EventSinks: TObjectList read GetEventSinks;
|
|
property Exceptions: TObjectList read GetExceptions;
|
|
|
|
property UnitName: string read GetUnitName write FUnitName;
|
|
property RequiredUnits: TStringList read FRequiredUnits write FRequiredUnits;
|
|
end;
|
|
|
|
TRODLSplitableConverterFileList = class (TObjectList)
|
|
private
|
|
function GetItem(Index: Integer): TRODLSplitableConverterFile;
|
|
procedure SetItem(Index: Integer; const Value: TRODLSplitableConverterFile);
|
|
public
|
|
property Items[Index: Integer]: TRODLSplitableConverterFile read GetItem write SetItem; default;
|
|
end;
|
|
|
|
|
|
implementation
|
|
|
|
uses
|
|
SysUtils, uRODLTemplateBasedConverterUtils;
|
|
|
|
{ TRODLSplitableConverter }
|
|
|
|
procedure TRODLSplitableConverter.AddEntityTypes(Types: {$IFDEF FPC}TStringList{$ELSE}THashedStringList{$ENDIF};
|
|
const AEntity: TRODLEntity; const unitName: string);
|
|
begin
|
|
Types.Values[AEntity.Name] := unitName;
|
|
end;
|
|
|
|
constructor TRODLSplitableConverter.Create(const aLibrary: TRODLLibrary;
|
|
const aTemplateFileName, aUnitName: string; const ASplit: Boolean;
|
|
const AOutputDir, AWrapperTemplateName, aTargetEntities: string);
|
|
begin
|
|
// Call inherited with nil so that convert is not called, allowing us
|
|
// to setup the optional sections. Setting up the optional sections before
|
|
// calling the inherited Create is not an option, the section list would
|
|
// not have been created
|
|
inherited Create(nil, aTemplateFileName, aUnitName, '');
|
|
FSplit := ASplit;
|
|
FFiles := TRODLSplitableConverterFileList.Create(True);
|
|
FOutputDir := AOutputDir;
|
|
if Length(FOutputDir) = 0 then
|
|
FOutputDir := '.';
|
|
FWrapperTemplateName := AWrapperTemplateName;
|
|
FTargetEntities := TStringList.Create;
|
|
FTargetEntities.Sorted := True;
|
|
FTargetEntities.Delimiter := ',';
|
|
FTargetEntities.DelimitedText := aTargetEntities;
|
|
|
|
// Setup the optional sections
|
|
|
|
// Now that everything is done, call convert if need be.
|
|
if (aLibrary <> nil) then Convert(aLibrary);
|
|
end;
|
|
|
|
destructor TRODLSplitableConverter.Destroy;
|
|
begin
|
|
FTargetEntities.Free;
|
|
FFiles.Free;
|
|
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TRODLSplitableConverter.ProcessTemplate(const aLibrary: TRODLLibrary;
|
|
template: TLineStream);
|
|
var
|
|
I: Integer;
|
|
curFile: TRODLSplitableConverterFile;
|
|
J: Integer;
|
|
UsesList: TStringList;
|
|
TypesList: {$IFDEF FPC}TStringList{$ELSE}THashedStringList{$ENDIF};
|
|
curEntity: TRODLEntity;
|
|
originalUnitName: string;
|
|
originalRequiredUnits: string;
|
|
oneEntitySelected: Boolean;
|
|
begin
|
|
if Split then
|
|
begin
|
|
SetupFiles(aLibrary);
|
|
ResolveRequiredUnits;
|
|
|
|
UsesList := TStringList.Create;
|
|
TypesList := {$IFDEF FPC}TStringList{$ELSE}THashedStringList{$ENDIF}.Create;
|
|
originalUnitName := UnitName;
|
|
originalRequiredUnits := RequiredUnits;
|
|
try
|
|
for I := 0 to FFiles.Count - 1 do
|
|
begin
|
|
curFile := FFiles[I];
|
|
|
|
UsesList.Add(curFile.UnitName);
|
|
|
|
FOrderedServices.Clear;
|
|
FOrderedArrays.Clear;
|
|
FOrderedStructs.Clear;
|
|
FOrderedEnums.Clear;
|
|
FOrderedExceptions.Clear;
|
|
FOrderedEventSinks.Clear;
|
|
|
|
oneEntitySelected := False;
|
|
for J := 0 to curFile.GetActiveList.Count - 1 do
|
|
begin
|
|
curEntity := curFile.GetActiveList[J] as TRODLEntity;
|
|
curFile.GetLibraryList.AddObject(curEntity.Name, curEntity);
|
|
AddEntityTypes(TypesList, curEntity, curFile.UnitName);
|
|
oneEntitySelected := oneEntitySelected or (FTargetEntities.IndexOf(curEntity.Name) > -1);
|
|
end;
|
|
|
|
// Only generate if no entities were indicated or if at least one
|
|
// of the entities in the current file was found earlier in the list.
|
|
if (FTargetEntities.Count = 0) or oneEntitySelected then
|
|
begin
|
|
Buffer.Clear;
|
|
template.Position := 0;
|
|
UnitName := curFile.UnitName;
|
|
RequiredUnits := originalRequiredUnits;
|
|
if curFile.RequiredUnits.Count > 0 then
|
|
begin
|
|
if Length(RequiredUnits) > 0 then
|
|
RequiredUnits := RequiredUnits + ',';
|
|
RequiredUnits := RequiredUnits + curFile.RequiredUnits.DelimitedText;
|
|
end;
|
|
inherited ProcessTemplate(aLibrary, template);
|
|
Buffer.SaveToFile(StrEnsureSuffix('\', OutputDir)+ curFile.UnitName + FileExtension);
|
|
end;
|
|
end;
|
|
|
|
UnitName := originalUnitName;
|
|
RequiredUnits := originalRequiredUnits;
|
|
WriteWrapper(TypesList, UsesList);
|
|
finally
|
|
UsesList.Free;
|
|
TypesList.Free;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
inherited ProcessTemplate(aLibrary, template);
|
|
end;
|
|
end;
|
|
|
|
procedure TRODLSplitableConverter.ResolveRequiredUnits;
|
|
var
|
|
curFileIndex: Integer;
|
|
curFile: TRODLSplitableConverterFile;
|
|
curEntityIndex: Integer;
|
|
curEntity: TRODLEntity;
|
|
curService: TRODLBaseService;
|
|
curArray: TRODLArray;
|
|
curStruct: TRODLBaseStruct;
|
|
typesCache: {$IFDEF FPC}TStringList{$ELSE}THashedStringList{$ENDIF};
|
|
curFieldIndex: Integer;
|
|
curOpIndex: Integer;
|
|
curOp: TRODLOperation;
|
|
curParamIndex: Integer;
|
|
notFounds: TStringList;
|
|
|
|
procedure AddRequiredUnits(const typeName: string);
|
|
var
|
|
resultIndex: Integer;
|
|
begin
|
|
resultIndex := notFounds.IndexOf(typeName);
|
|
if resultIndex = -1 then
|
|
begin
|
|
unitName := typesCache.Values[typeName];
|
|
if Length(unitName) > 0 then
|
|
begin
|
|
if unitName <> curFile.UnitName then
|
|
curFile.RequiredUnits.Add(unitName);
|
|
end
|
|
else
|
|
begin
|
|
notFounds.Add(typeName);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
// In order to find out if a splitted file requires other files, we need
|
|
// to know which types are where. So we fill in the typesCache list with
|
|
// Name/Value pairs, where the name is the type and the value the unit
|
|
// where it is located.
|
|
// Once this is done, we go look at all the types in all the files, and
|
|
// we look for them in the cache. If the type is found, then the unit it
|
|
// resides in is added to the list of required units. If it is not found
|
|
// it is added to the notFounds list. This second list allows to speed
|
|
// the process a lot because looking through the typesCache list is slow
|
|
// and many regular types (Integer, String...) are used a lot but there are
|
|
// not many of them. Hence the second list allows to know very fast for these
|
|
// that they were not found in any unit.
|
|
typesCache := {$IFDEF FPC}TStringList{$ELSE}THashedStringList{$ENDIF}.Create;
|
|
notFounds := TStringList.Create;
|
|
try
|
|
notFounds.Sorted := True;
|
|
|
|
for curFileIndex := 0 to FFiles.Count - 1 do
|
|
begin
|
|
curFile := FFiles[curFileIndex];
|
|
|
|
for curEntityIndex := 0 to curFile.GetActiveList.Count - 1 do
|
|
begin
|
|
curEntity := curFile.GetActiveList[curEntityIndex] as TRODLEntity;
|
|
typesCache.Values[curEntity.Name] := curFile.UnitName;
|
|
end;
|
|
end;
|
|
|
|
for curFileIndex := 0 to FFiles.Count - 1 do
|
|
begin
|
|
curFile := FFiles[curFileIndex];
|
|
|
|
curFile.RequiredUnits.Clear;
|
|
for curEntityIndex := 0 to curFile.GetActiveList.Count - 1 do
|
|
begin
|
|
curEntity := curFile.GetActiveList[curEntityIndex] as TRODLEntity;
|
|
if curEntity is TRODLBaseService then
|
|
begin
|
|
curService := curEntity as TRODLBaseService;
|
|
|
|
AddRequiredUnits(curService.Ancestor);
|
|
|
|
for curOpIndex := 0 to curService.Default.Count - 1 do
|
|
begin
|
|
curOp := curService.Default.Items[curOpIndex];
|
|
if Assigned(curOp.Result) then
|
|
AddRequiredUnits(curOp.Result.DataType);
|
|
|
|
for curParamIndex := 0 to curOp.Count - 1 do
|
|
AddRequiredUnits(curOp.Items[curParamIndex].DataType);
|
|
end;
|
|
end
|
|
else
|
|
if curEntity is TRODLArray then
|
|
begin
|
|
curArray := curEntity as TRODLArray;
|
|
AddRequiredUnits(curArray.ElementType);
|
|
end
|
|
else
|
|
if curEntity is TRODLBaseStruct then
|
|
begin
|
|
curStruct := curEntity as TRODLBaseStruct;
|
|
|
|
AddRequiredUnits(curStruct.Ancestor);
|
|
|
|
for curFieldIndex := 0 to curStruct.Count - 1 do
|
|
AddRequiredUnits(curStruct.Items[curFieldIndex].DataType);
|
|
end;
|
|
end;
|
|
curFile.RequiredUnits.Delimiter := ',';
|
|
end;
|
|
finally
|
|
notFounds.Free;
|
|
typesCache.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TRODLSplitableConverter.WriteWrapper(TypesList,
|
|
UsesList: TStringList);
|
|
var
|
|
template: TLineStream;
|
|
content: TStringList;
|
|
curLine: string;
|
|
sectionContent: string;
|
|
I: Integer;
|
|
typeUnitName: string;
|
|
begin
|
|
template := TLineStream.Create('');
|
|
try
|
|
content := TStringList.Create;
|
|
try
|
|
if FileExists(FWrapperTemplateName) then
|
|
content.LoadFromFile(FWrapperTemplateName)
|
|
else
|
|
LoadTemplateFromResource(content, FWrapperTemplateName);
|
|
|
|
template.WriteString(content.Text);
|
|
template.Position := 0;
|
|
finally
|
|
content.Free;
|
|
end;
|
|
|
|
Buffer.Clear;
|
|
while not template.Eof do
|
|
begin
|
|
curLine := template.ReadLine;
|
|
|
|
MacroReplace(curLine, '%',
|
|
['UNIT_NAME', FLibrary.Name + SplitFilesSuffix
|
|
]);
|
|
|
|
if SectionStart(curLine, 'USES') then
|
|
begin
|
|
sectionContent := FinishSection('USES', template);
|
|
|
|
for I := 0 to UsesList.Count - 1 do
|
|
begin
|
|
curLine := sectionContent;
|
|
MacroReplace(curLine, '%',
|
|
['USED_UNIT_NAME', UsesList[I]
|
|
]);
|
|
|
|
if I = UsesList.Count-1 then
|
|
curLine := StrEnsureNoSuffix(',', curLine);
|
|
Write(curLine);
|
|
end;
|
|
end
|
|
else
|
|
if SectionStart(curLine, 'TYPES') then
|
|
begin
|
|
sectionContent := FinishSection('TYPES', template);
|
|
|
|
for I := 0 to TypesList.Count - 1 do
|
|
begin
|
|
curLine := sectionContent;
|
|
typeUnitName := TypesList[I];
|
|
typeUnitName := Copy(typeUnitName, Pos('=', typeUnitName)+1, MAXINT);
|
|
MacroReplace(curLine, '%',
|
|
['TYPE_UNIT_NAME', typeUnitName,
|
|
'TYPE_NAME', TypesList.Names[I]
|
|
]);
|
|
Write(curLine);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
Write(curLine);
|
|
end;
|
|
end;
|
|
finally
|
|
template.Free;
|
|
end;
|
|
end;
|
|
|
|
{ TRODLIntfConverterFileList }
|
|
|
|
function TRODLSplitableConverterFileList.GetItem(
|
|
Index: Integer): TRODLSplitableConverterFile;
|
|
begin
|
|
Result := inherited Items[Index] as TRODLSplitableConverterFile;
|
|
end;
|
|
|
|
procedure TRODLSplitableConverterFileList.SetItem(Index: Integer;
|
|
const Value: TRODLSplitableConverterFile);
|
|
begin
|
|
inherited Items[Index] := Value;
|
|
end;
|
|
|
|
{ TRODLIntfConverterFile }
|
|
|
|
constructor TRODLSplitableConverterFile.Create(const aLibrary: TRODLLibrary; const aConverter: TRODLSplitableConverter);
|
|
begin
|
|
inherited Create;
|
|
|
|
FLibrary := aLibrary;
|
|
FConverter := aConverter;
|
|
FRequiredUnits := TStringList.Create;
|
|
FRequiredUnits.Sorted := True;
|
|
FRequiredUnits.Duplicates := dupIgnore;
|
|
end;
|
|
|
|
destructor TRODLSplitableConverterFile.Destroy;
|
|
begin
|
|
FRequiredUnits.Free;
|
|
FEnums.Free;
|
|
FArrays.Free;
|
|
FStructs.Free;
|
|
FEventSinks.Free;
|
|
FExceptions.Free;
|
|
FServices.Free;
|
|
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TRODLSplitableConverterFile.GetActiveList: TObjectList;
|
|
begin
|
|
if FActiveList = nil then
|
|
begin
|
|
SetupLists;
|
|
end;
|
|
Result := FActiveList;
|
|
end;
|
|
|
|
procedure TRODLSplitableConverterFile.SetupLists;
|
|
begin
|
|
if Services.Count > 0 then
|
|
begin
|
|
FActiveList := Services;
|
|
FLibraryList := FConverter.OrderedServices;
|
|
end
|
|
else if Arrays.Count > 0 then
|
|
begin
|
|
FActiveList := Arrays;
|
|
FLibraryList := FConverter.OrderedArrays;
|
|
end
|
|
else if Structs.Count > 0 then
|
|
begin
|
|
FActiveList := Structs;
|
|
FLibraryList := FConverter.OrderedStructs;
|
|
end
|
|
else if Enums.Count > 0 then
|
|
begin
|
|
FActiveList := Enums;
|
|
FLibraryList := FConverter.OrderedEnums;
|
|
end
|
|
else if EventSinks.Count > 0 then
|
|
begin
|
|
FActiveList := EventSinks;
|
|
FLibraryList := FConverter.OrderedEventSinks;
|
|
end
|
|
else if Exceptions.Count > 0 then
|
|
begin
|
|
FActiveList := Exceptions;
|
|
FLibraryList := FConverter.OrderedExceptions;
|
|
end;
|
|
end;
|
|
|
|
function TRODLSplitableConverterFile.GetArrays: TObjectList;
|
|
begin
|
|
if not Assigned(FArrays) then
|
|
FArrays := TObjectList.Create(False);
|
|
Result := FArrays;
|
|
end;
|
|
|
|
function TRODLSplitableConverterFile.GetEnums: TObjectList;
|
|
begin
|
|
if not Assigned(FEnums) then
|
|
FEnums := TObjectList.Create(False);
|
|
Result := FEnums;
|
|
end;
|
|
|
|
function TRODLSplitableConverterFile.GetEventSinks: TObjectList;
|
|
begin
|
|
if not Assigned(FEventSinks) then
|
|
FEventSinks := TObjectList.Create(False);
|
|
Result := FEventSinks;
|
|
end;
|
|
|
|
function TRODLSplitableConverterFile.GetExceptions: TObjectList;
|
|
begin
|
|
if not Assigned(FExceptions) then
|
|
FExceptions := TObjectList.Create(False);
|
|
Result := FExceptions;
|
|
end;
|
|
|
|
function TRODLSplitableConverterFile.GetLibraryList: IROStrings;
|
|
begin
|
|
if FLibraryList = nil then
|
|
begin
|
|
SetupLists;
|
|
end;
|
|
Result := FLibraryList;
|
|
end;
|
|
|
|
function TRODLSplitableConverterFile.GetServices: TObjectList;
|
|
begin
|
|
if not Assigned(FServices) then
|
|
FServices := TObjectList.Create(False);
|
|
Result := FServices;
|
|
end;
|
|
|
|
function TRODLSplitableConverterFile.GetStructs: TObjectList;
|
|
begin
|
|
if not Assigned(FStructs) then
|
|
FStructs := TObjectList.Create(False);
|
|
Result := FStructs;
|
|
end;
|
|
|
|
function TRODLSplitableConverterFile.GetUnitName: string;
|
|
var
|
|
list: TObjectList;
|
|
I: Integer;
|
|
begin
|
|
if FUnitName = '' then
|
|
begin
|
|
list := GetActiveList;
|
|
for I := 0 to list.Count - 1 do
|
|
FUnitName := FUnitName + (list[i] as TRODLEntity).Name + '_';
|
|
FUnitName := FLibrary.Name + '_' + Copy(FUnitName, 1, Length(FUnitName)-1) + FConverter.SplitFilesSuffix;
|
|
end;
|
|
Result := FUnitName;
|
|
end;
|
|
|
|
end.
|