Converter: optionally delete files in project dir if LCL has a unit with same name.

git-svn-id: trunk@41665 -
This commit is contained in:
juha 2013-06-10 14:32:53 +00:00
parent 8c2b602dda
commit cff5dd3116
4 changed files with 84 additions and 33 deletions

View File

@ -23,7 +23,7 @@
Abstract: Abstract:
Convert Delphi projects/packages to lazarus projects/packages. Convert Delphi projects/packages to lazarus projects/packages.
This was refactored and cleaned from code in unit DelphiProject2Laz. This was refactored and cleaned from code in unit DelphiProject2Laz.
Now it is objects oriented and easier to maintain / improve. Now it is object oriented and easier to maintain / improve.
} }
unit ConvertDelphi; unit ConvertDelphi;
@ -41,7 +41,7 @@ uses
// IDEIntf // IDEIntf
ComponentReg, IDEMsgIntf, MainIntf, LazIDEIntf, PackageIntf, ProjectIntf, ComponentReg, IDEMsgIntf, MainIntf, LazIDEIntf, PackageIntf, ProjectIntf,
// IDE // IDE
IDEProcs, Project, ProjectDefs, DialogProcs, EditorOptions, CompilerOptions, IDEProcs, Project, ProjectDefs, DialogProcs, IDEDialogs, EditorOptions, CompilerOptions,
PackageDefs, PackageSystem, PackageEditor, BasePkgManager, LazarusIDEStrConsts, PackageDefs, PackageSystem, PackageEditor, BasePkgManager, LazarusIDEStrConsts,
// Converter // Converter
ConverterTypes, ConvertSettings, ConvCodeTool, MissingUnits, MissingPropertiesDlg, ConverterTypes, ConvertSettings, ConvCodeTool, MissingUnits, MissingPropertiesDlg,
@ -137,7 +137,7 @@ type
function DoMissingUnits(AUsedUnitsTool: TUsedUnitsTool): integer; virtual; function DoMissingUnits(AUsedUnitsTool: TUsedUnitsTool): integer; virtual;
function GetCachedUnitPath(const AUnitName: string): string; function GetCachedUnitPath(const AUnitName: string): string;
protected protected
function EndConvert(AStatus: TModalResult): Boolean; procedure EndConvert(AStatus: TModalResult);
public public
constructor Create(const AFilename, ADescription: string); constructor Create(const AFilename, ADescription: string);
destructor Destroy; override; destructor Destroy; override;
@ -174,8 +174,9 @@ type
fMainUnitConverter: TDelphiUnit; fMainUnitConverter: TDelphiUnit;
// Unit search path for project settings. // Unit search path for project settings.
fUnitSearchPaths: TStringList; fUnitSearchPaths: TStringList;
// Units that are found and will be added to project and converted. // Units that are found and will be added to project or package and converted.
fUnitsToAddToProject: TStringList; fUnitsToAddToProject: TStringList;
fFilesToDelete: TStringList;
fUseThreads: boolean; // The project/package uses TThread. fUseThreads: boolean; // The project/package uses TThread.
function ConvertSub: TModalResult; function ConvertSub: TModalResult;
procedure CleanUpCompilerOptionsSearchPaths(Options: TBaseCompilerOptions); procedure CleanUpCompilerOptionsSearchPaths(Options: TBaseCompilerOptions);
@ -187,6 +188,7 @@ type
function ExtractOptionsFromCFG(const CFGFilename: string): TModalResult; function ExtractOptionsFromCFG(const CFGFilename: string): TModalResult;
function DoMissingUnits(AUsedUnitsTool: TUsedUnitsTool): integer; override; function DoMissingUnits(AUsedUnitsTool: TUsedUnitsTool): integer; override;
function AddToProjectLater(AFileName: string): Boolean; function AddToProjectLater(AFileName: string): Boolean;
function MaybeDeleteFiles: TModalResult;
function CheckPackageDep(AUnitName: string): Boolean; function CheckPackageDep(AUnitName: string): Boolean;
function TryAddPackageDep(AUnitName, ADefaultPkgName: string): Boolean; function TryAddPackageDep(AUnitName, ADefaultPkgName: string): Boolean;
protected protected
@ -471,7 +473,7 @@ end;
{ TDelphiUnit } { TDelphiUnit }
constructor TDelphiUnit.Create(AOwnerConverter: TConvertDelphiPBase; constructor TDelphiUnit.Create(AOwnerConverter: TConvertDelphiPBase;
const AFilename: string; AFlags: TConvertUnitFlags); const AFilename: string; aFlags: TConvertUnitFlags);
begin begin
inherited Create; inherited Create;
fOwnerConverter:=AOwnerConverter; fOwnerConverter:=AOwnerConverter;
@ -510,7 +512,8 @@ begin
fOwnerConverter.fSettings.AddLogLine(Format(lisConvDelphiConvertingFile, fOwnerConverter.fSettings.AddLogLine(Format(lisConvDelphiConvertingFile,
[fOrigUnitFilename])); [fOrigUnitFilename]));
Application.ProcessMessages; Application.ProcessMessages;
// ConvertUnit in place. File must be writable.
// Convert unit in place. File must be writable.
Result:=CheckFileIsWritable(fOrigUnitFilename,[mbAbort]); Result:=CheckFileIsWritable(fOrigUnitFilename,[mbAbort]);
if Result<>mrOK then exit; if Result<>mrOK then exit;
// close Delphi unit file in editor. // close Delphi unit file in editor.
@ -852,7 +855,7 @@ begin
Result:=fCachedUnitNames[AUnitName]; Result:=fCachedUnitNames[AUnitName];
end; end;
function TConvertDelphiPBase.EndConvert(AStatus: TModalResult): Boolean; procedure TConvertDelphiPBase.EndConvert(AStatus: TModalResult);
begin begin
// Show ending message // Show ending message
if AStatus=mrOK then if AStatus=mrOK then
@ -931,12 +934,15 @@ begin
fAllCommentedUnits.Sorted:=True; fAllCommentedUnits.Sorted:=True;
fUnitsToAddToProject:=TStringList.Create; fUnitsToAddToProject:=TStringList.Create;
fUnitsToAddToProject.Sorted:=True; fUnitsToAddToProject.Sorted:=True;
fFilesToDelete:=TStringList.Create;
fFilesToDelete.Sorted:=True;
fMainUnitConverter:=nil; fMainUnitConverter:=nil;
end; end;
destructor TConvertDelphiProjPack.Destroy; destructor TConvertDelphiProjPack.Destroy;
begin begin
fMainUnitConverter.Free; fMainUnitConverter.Free;
fFilesToDelete.Free;
fUnitsToAddToProject.Free; fUnitsToAddToProject.Free;
fAllCommentedUnits.Free; fAllCommentedUnits.Free;
fCachedRealFileNames.Free; fCachedRealFileNames.Free;
@ -1043,9 +1049,11 @@ begin
Result:=fMainUnitConverter.ConvertFormFile; Result:=fMainUnitConverter.ConvertFormFile;
if Result<>mrOK then exit; if Result<>mrOK then exit;
Result:=ConvertAllUnits; // convert all files. Result:=ConvertAllUnits; // convert all files.
if Result<>mrOK then exit;
finally finally
UnsetCompilerModeForDefineTempl(CustomDefines); UnsetCompilerModeForDefineTempl(CustomDefines);
end; end;
Result:=MaybeDeleteFiles; // Delete files having same name with a LCL unit.
end; end;
function TConvertDelphiProjPack.ConvertAllFormFiles(ConverterList: TObjectList): TModalResult; function TConvertDelphiProjPack.ConvertAllFormFiles(ConverterList: TObjectList): TModalResult;
@ -1315,10 +1323,33 @@ var
x: Integer; x: Integer;
begin begin
Result:=not fUnitsToAddToProject.Find(AFileName,x); Result:=not fUnitsToAddToProject.Find(AFileName,x);
if Result then if Result then // Add the file later to project if not already done.
fUnitsToAddToProject.Add(AFileName); fUnitsToAddToProject.Add(AFileName);
end; end;
function TConvertDelphiProjPack.MaybeDeleteFiles: TModalResult;
// Maybe delete files that are already in LCL. They are potentially copied from VCL.
var
s: String;
i: Integer;
begin
for i := fFilesToDelete.Count-1 downto 0 do begin
s:=fFilesToDelete[i];
// Ask confirmation from user.
if IDEMessageDialog(lisConvDelphiUnitnameExistsInLCL,
Format(lisConvDelphiUnitWithNameExistsInLCL, [ExtractFileNameOnly(s)]),
mtConfirmation, mbYesNo) = mrYes
then begin
// Delete from file system because compiler would find it otherwise.
if not DeleteFileUTF8(s) then
exit(mrCancel);
//fFilesToDelete.Delete(i);
fSettings.AddLogLine(Format('Deleted file %s',[s]));
end;
end;
Result:=mrOK;
end;
function TConvertDelphiProjPack.CheckPackageDep(AUnitName: string): Boolean; function TConvertDelphiProjPack.CheckPackageDep(AUnitName: string): Boolean;
// Check if the given unit can be found in existing packages. Add a dependency if found. // Check if the given unit can be found in existing packages. Add a dependency if found.
// This is called only if the unit is reported as missing. // This is called only if the unit is reported as missing.
@ -1479,8 +1510,10 @@ begin
if FilenameIsPascalUnit(AFileName) then begin if FilenameIsPascalUnit(AFileName) then begin
CurUnitInfo:=LazProject.UnitWithUnitname(PureUnitName); CurUnitInfo:=LazProject.UnitWithUnitname(PureUnitName);
if CurUnitInfo<>nil then begin if CurUnitInfo<>nil then begin
Result:=QuestionDlg(lisConvDelphiUnitnameExistsTwice, raise Exception.CreateFmt('TConvertDelphiProject.AddUnit: Unitname %s exists twice',
Format(lisConvDelphiThereAreTwoUnitsWithTheSameUnitname, [PureUnitName]);
{ Result:=QuestionDlg(lisConvDelphiUnitnameExistsTwice,
Format(lisConvDelphiTwoUnitsWithSameName,
[LineEnding, CurUnitInfo.Filename, LineEnding, AFileName, LineEnding]), [LineEnding, CurUnitInfo.Filename, LineEnding, AFileName, LineEnding]),
mtWarning, [mrYes,lisConvDelphiRemoveFirst,mrNo,lisConvDelphiRemoveSecond, mtWarning, [mrYes,lisConvDelphiRemoveFirst,mrNo,lisConvDelphiRemoveSecond,
mrIgnore,lisConvDelphiKeepBoth,mrAbort], 0); mrIgnore,lisConvDelphiKeepBoth,mrAbort], 0);
@ -1493,6 +1526,7 @@ begin
exit(mrAbort); exit(mrAbort);
end; end;
end; end;
}
end; end;
end; end;
CurUnitInfo:=TUnitInfo.Create(nil); CurUnitInfo:=TUnitInfo.Create(nil);
@ -1505,16 +1539,30 @@ begin
end; end;
function TConvertDelphiProject.CheckUnitForConversion(aFileName: string): Boolean; function TConvertDelphiProject.CheckUnitForConversion(aFileName: string): Boolean;
// Units in project directory but not part of the project are not reported
// as missing and would not be converted. Now add them to the project.
// ToDo: move to TConvertDelphiProjPack and support packages, too.
var var
UnitInfo: TUnitInfo; UnitInfo: TUnitInfo;
PkgFile: TPkgFile;
PureUnitName: String;
x: Integer;
begin begin
// Units in project directory but not part of the project are not reported
// as missing and would not be converted. Now add them to the project.
if ExtractFilePath(aFileName)=LazProject.ProjectDirectory then begin if ExtractFilePath(aFileName)=LazProject.ProjectDirectory then begin
UnitInfo:=LazProject.UnitInfoWithFilename(aFileName); UnitInfo:=LazProject.UnitInfoWithFilename(aFileName);
Result:=Assigned(UnitInfo); Result:=not Assigned(UnitInfo);
if not Result then if Result then begin
AddToProjectLater(aFileName); // Will be added later to project. // Not in project.
// Check if unit with same name already exists in LCL, maybe copied from VCL.
PureUnitName:=ExtractFileNameOnly(AFileName);
PkgFile:=PackageGraph.LCLBasePackage.FindUnit(PureUnitName);
if Assigned(PkgFile) then begin
if not fFilesToDelete.Find(aFileName, x) then
fFilesToDelete.Add(AFileName); // Found also in LCL, delete later.
end;
//else
AddToProjectLater(aFileName); // Add to project later.
end;
end; end;
end; end;
@ -1809,7 +1857,7 @@ var
CodeBuffer: TCodeBuffer; CodeBuffer: TCodeBuffer;
Flags: TPkgFileFlags; Flags: TPkgFileFlags;
HasRegisterProc: boolean; HasRegisterProc: boolean;
UnitN: String; PureUnitName: String;
begin begin
Result:=mrOK; Result:=mrOK;
if not FilenameIsAbsolute(AFileName) then if not FilenameIsAbsolute(AFileName) then
@ -1819,12 +1867,15 @@ begin
exit(mrNo); exit(mrNo);
PkgFile:=LazPackage.FindPkgFile(AFileName,true,false); PkgFile:=LazPackage.FindPkgFile(AFileName,true,false);
if PkgFile=nil then begin if PkgFile=nil then begin
PureUnitName:=ExtractFileNameOnly(AFileName);
if FilenameIsPascalUnit(AFileName) then begin if FilenameIsPascalUnit(AFileName) then begin
// Check unitname // Check unitname
OffendingUnit:=LazPackage.FindUnit(ExtractFileNameOnly(AFileName)); OffendingUnit:=LazPackage.FindUnit(PureUnitName);
if OffendingUnit<>nil then begin if OffendingUnit<>nil then begin
Result:=QuestionDlg(lisConvDelphiUnitnameExistsTwice, raise Exception.CreateFmt('TConvertDelphiPackage.AddUnit: Unitname %s exists twice',
Format(lisConvDelphiThereAreTwoUnitsWithTheSameUnitname, [PureUnitName]);
{ Result:=QuestionDlg(lisConvDelphiUnitnameExistsTwice,
Format(lisConvDelphiTwoUnitsWithSameName,
[LineEnding, OffendingUnit.Filename, LineEnding, AFileName, LineEnding]), [LineEnding, OffendingUnit.Filename, LineEnding, AFileName, LineEnding]),
mtWarning, [mrNo, lisConvDelphiRemoveSecond, mrAbort], 0); mtWarning, [mrNo, lisConvDelphiRemoveSecond, mrAbort], 0);
case Result of case Result of
@ -1835,9 +1886,9 @@ begin
exit(mrAbort); exit(mrAbort);
end; end;
end; end;
}
end; end;
end; end;
UnitN:=ExtractFileNameOnly(AFileName);
Flags:=[pffAddToPkgUsesSection]; Flags:=[pffAddToPkgUsesSection];
// Check if the unit has a Register procedure. // Check if the unit has a Register procedure.
// ToDo: Optimize. The source is read again during unit conversion. // ToDo: Optimize. The source is read again during unit conversion.
@ -1847,10 +1898,10 @@ begin
if HasRegisterProc then begin if HasRegisterProc then begin
Include(Flags, pffHasRegisterProc); Include(Flags, pffHasRegisterProc);
fSettings.AddLogLine(Format('Adding flag for "Register" procedure in unit %s.', fSettings.AddLogLine(Format('Adding flag for "Register" procedure in unit %s.',
[UnitN])); [PureUnitName]));
end; end;
// Add new unit to package // Add new unit to package
LazPackage.AddFile(AFileName, UnitN, pftUnit, Flags, cpNormal); LazPackage.AddFile(AFileName, PureUnitName, pftUnit, Flags, cpNormal);
end; end;
end; end;

View File

@ -106,7 +106,7 @@ type
function BackupFile(const AFilename: string): TModalResult; function BackupFile(const AFilename: string): TModalResult;
procedure ClearLog; procedure ClearLog;
function AddLogLine(const ALine: string): integer; function AddLogLine(const ALine: string): integer;
function SaveLog: Boolean; procedure SaveLog;
public public
property MainFilename: String read fMainFilename write SetMainFilename; property MainFilename: String read fMainFilename write SetMainFilename;
property MainPath: String read fMainPath; property MainPath: String read fMainPath;
@ -787,7 +787,7 @@ begin
Result:=fLog.Add(ALine); // and store for log. Result:=fLog.Add(ALine); // and store for log.
end; end;
function TConvertSettings.SaveLog: Boolean; procedure TConvertSettings.SaveLog;
var var
aFilename: String; aFilename: String;
Code: TCodeBuffer; Code: TCodeBuffer;

View File

@ -251,8 +251,9 @@ begin
fMissingUnits.Add(OldUnitName); fMissingUnits.Add(OldUnitName);
end; end;
// Check if the unit is not part of project. It will be added and converted then. // Check if the unit is not part of project. It will be added and converted then.
if Assigned(fOwnerTool.OnCheckUnitForConversion) then if not fOwnerTool.IsMainFile then
fOwnerTool.OnCheckUnitForConversion(FullFileN); if Assigned(fOwnerTool.OnCheckUnitForConversion) then
fOwnerTool.OnCheckUnitForConversion(FullFileN);
end end
else begin // * Unit not found * else begin // * Unit not found *
// Add unit to fMissingUnits, but don't add Windows specific units if target // Add unit to fMissingUnits, but don't add Windows specific units if target
@ -574,11 +575,9 @@ begin
MapToEdit:=TStringToStringTree.Create(false); MapToEdit:=TStringToStringTree.Create(false);
fCTLink.CodeTool.BuildTree(lsrEnd); fCTLink.CodeTool.BuildTree(lsrEnd);
if not (fMainUsedUnits.FindMissingUnits(UnitUpdater) and if not (fMainUsedUnits.FindMissingUnits(UnitUpdater) and
fImplUsedUnits.FindMissingUnits(UnitUpdater)) then begin fImplUsedUnits.FindMissingUnits(UnitUpdater)) then
Result:=mrCancel; exit(mrCancel);
exit;
end;
if Result<>mrOK then exit;
// Find replacements for missing units from settings. // Find replacements for missing units from settings.
fMainUsedUnits.FindReplacement(UnitUpdater, MapToEdit); fMainUsedUnits.FindReplacement(UnitUpdater, MapToEdit);
fImplUsedUnits.FindReplacement(UnitUpdater, MapToEdit); fImplUsedUnits.FindReplacement(UnitUpdater, MapToEdit);

View File

@ -5436,8 +5436,9 @@ resourcestring
lisConvDelphiExceptionDuringConversion = 'Exception happened during unit conversion.' lisConvDelphiExceptionDuringConversion = 'Exception happened during unit conversion.'
+' Continuing with form files of already converted units...'; +' Continuing with form files of already converted units...';
lisConvDelphiUnitnameExistsTwice = 'Unitname exists twice'; lisConvDelphiUnitnameExistsTwice = 'Unitname exists twice';
lisConvDelphiThereAreTwoUnitsWithTheSameUnitname = 'There are two units ' lisConvDelphiTwoUnitsWithSameName = 'There are two units with the same name:%s%s%s%s%s';
+'with the same unitname:%s%s%s%s%s'; lisConvDelphiUnitnameExistsInLCL = 'Unitname exists in LCL';
lisConvDelphiUnitWithNameExistsInLCL = 'LCL already has a unit with name %s. Delete it?';
lisConvDelphiRemoveFirst = 'Remove first'; lisConvDelphiRemoveFirst = 'Remove first';
lisConvDelphiRemoveSecond = 'Remove second'; lisConvDelphiRemoveSecond = 'Remove second';
lisConvDelphiKeepBoth = 'Keep both'; lisConvDelphiKeepBoth = 'Keep both';