Converter: add needed units to uses section automatically. A class in LCL can be in a different unit than in VCL. Issue #23900

git-svn-id: trunk@40558 -
This commit is contained in:
juha 2013-03-16 14:37:13 +00:00
parent f69ac681f1
commit a13843f26c
3 changed files with 87 additions and 47 deletions

View File

@ -672,7 +672,7 @@ begin
LfmFixer.RootMustBeClassInUnit:=true; LfmFixer.RootMustBeClassInUnit:=true;
LfmFixer.RootMustBeClassInIntf:=true; LfmFixer.RootMustBeClassInIntf:=true;
LfmFixer.ObjectsMustExist:=true; LfmFixer.ObjectsMustExist:=true;
if LfmFixer.Repair<>mrOk then begin if LfmFixer.ConvertAndRepair<>mrOk then begin
LazarusIDE.DoJumpToCompilerMessage(-1,true); LazarusIDE.DoJumpToCompilerMessage(-1,true);
fOwnerConverter.fErrorMsg:='Problems when repairing form file ' fOwnerConverter.fErrorMsg:='Problems when repairing form file '
+fOrigUnitFilename; +fOrigUnitFilename;

View File

@ -42,7 +42,7 @@ uses
// IDE // IDE
IDEDialogs, ComponentReg, PackageIntf, IDEWindowIntf, DialogProcs, IDEDialogs, ComponentReg, PackageIntf, IDEWindowIntf, DialogProcs,
CustomFormEditor, LazarusIDEStrConsts, IDEProcs, OutputFilter, CustomFormEditor, LazarusIDEStrConsts, IDEProcs, OutputFilter,
EditorOptions, CheckLFMDlg, IDEMsgIntf, EditorOptions, CheckLFMDlg, IDEMsgIntf, Project,
// Converter // Converter
ConverterTypes, ConvertSettings, ReplaceNamesUnit, ConverterTypes, ConvertSettings, ReplaceNamesUnit,
ConvCodeTool, FormFileConv, UsedUnits; ConvCodeTool, FormFileConv, UsedUnits;
@ -83,14 +83,15 @@ type
function AddNewProps(aNewProps: TList): TModalResult; function AddNewProps(aNewProps: TList): TModalResult;
// Fill StringGrids with missing properties and types from fLFMTree. // Fill StringGrids with missing properties and types from fLFMTree.
procedure FillReplaceGrids; procedure FillReplaceGrids;
function ShowConvertLFMWizard: TModalResult;
protected protected
function FixMissingComponentClasses(aMissingTypes: TStringList): TModalResult; override;
procedure LoadLFM; procedure LoadLFM;
function ShowRepairLFMWizard: TModalResult; override;
public public
constructor Create(ACTLink: TCodeToolLink; ALFMBuffer: TCodeBuffer; constructor Create(ACTLink: TCodeToolLink; ALFMBuffer: TCodeBuffer;
const AOnOutput: TOnAddFilteredLine); const AOnOutput: TOnAddFilteredLine);
destructor Destroy; override; destructor Destroy; override;
function Repair: TModalResult; function ConvertAndRepair: TModalResult;
public public
property Settings: TConvertSettings read fSettings write fSettings; property Settings: TConvertSettings read fSettings write fSettings;
property UsedUnitsTool: TUsedUnitsTool read fUsedUnitsTool write fUsedUnitsTool; property UsedUnitsTool: TUsedUnitsTool read fUsedUnitsTool write fUsedUnitsTool;
@ -311,11 +312,6 @@ begin
AddReplacement(ChgEntryRepl,StartPos,EndPos,NewIdent); AddReplacement(ChgEntryRepl,StartPos,EndPos,NewIdent);
IDEMessagesWindow.AddMsg(Format( IDEMessagesWindow.AddMsg(Format(
'Replaced type "%s" with "%s".',[OldIdent, NewIdent]),'',-1); 'Replaced type "%s" with "%s".',[OldIdent, NewIdent]),'',-1);
if Assigned(fUsedUnitsTool) then begin
// ToDo: This is a test and will be replaced by configurable unit names.
if NewIdent='TRichMemo' then
fUsedUnitsTool.AddUnitIfNeeded('RichMemo');
end;
Result:=mrRetry; Result:=mrRetry;
end; end;
end end
@ -436,13 +432,7 @@ begin
end; end;
end; end;
procedure TLFMFixer.LoadLFM; function TLFMFixer.ShowConvertLFMWizard: TModalResult;
begin
inherited LoadLFM;
FillReplaceGrids; // Fill both ReplaceGrids.
end;
function TLFMFixer.ShowRepairLFMWizard: TModalResult;
var var
FixLFMDialog: TFixLFMDialog; FixLFMDialog: TFixLFMDialog;
PrevCursor: TCursor; PrevCursor: TCursor;
@ -473,7 +463,44 @@ begin
end; end;
end; end;
function TLFMFixer.Repair: TModalResult; function TLFMFixer.FixMissingComponentClasses(aMissingTypes: TStringList): TModalResult;
// This is called from TLFMChecker.FindAndFixMissingComponentClasses.
// Add needed units to uses section using methods already defined in fUsedUnitsTool.
var
RegComp: TRegisteredComponent;
ClassUnitInfo: TUnitInfo;
i: Integer;
CompClassName, NeededUnitName: String;
begin
Result:=mrOK;
if not Assigned(fUsedUnitsTool) then Exit;
for i := 0 to aMissingTypes.Count-1 do begin
CompClassName := aMissingTypes[i];
RegComp:=IDEComponentPalette.FindComponent(CompClassName);
NeededUnitName:='';
if (RegComp<>nil) then begin
if RegComp.ComponentClass<>nil then begin
NeededUnitName:=RegComp.ComponentClass.UnitName;
if NeededUnitName='' then
NeededUnitName:=RegComp.GetUnitName;
end;
end else begin
ClassUnitInfo:=Project1.UnitWithComponentClassName(CompClassName);
if ClassUnitInfo<>nil then
NeededUnitName:=ClassUnitInfo.Unit_Name;
end;
if NeededUnitName<>'' then
fUsedUnitsTool.AddUnitIfNeeded(NeededUnitName);
end;
end;
procedure TLFMFixer.LoadLFM;
begin
inherited LoadLFM;
FillReplaceGrids; // Fill both ReplaceGrids.
end;
function TLFMFixer.ConvertAndRepair: TModalResult;
var var
ConvTool: TConvDelphiCodeTool; ConvTool: TConvDelphiCodeTool;
FormFileTool: TFormFileConverter; FormFileTool: TFormFileConverter;
@ -499,13 +526,24 @@ begin
fRootMustBeClassInUnit, fRootMustBeClassInIntf, fObjectsMustExist) then fRootMustBeClassInUnit, fRootMustBeClassInIntf, fObjectsMustExist) then
Result:=mrOk Result:=mrOk
else // Rename/remove properties and types interactively. else // Rename/remove properties and types interactively.
Result:=ShowRepairLFMWizard; // Can return mrRetry. Result:=ShowConvertLFMWizard; // Can return mrRetry.
Inc(LoopCount); Inc(LoopCount);
until (Result in [mrOK, mrCancel]) or (LoopCount=10); until (Result in [mrOK, mrCancel]) or (LoopCount=10);
// Show remaining errors to user.
WriteLFMErrors; // Check for missing object types and add units as needed.
if (Result=mrOK) and (fSettings.CoordOffsMode=rsEnabled) then begin if not fLFMTree.ParseIfNeeded then
Exit(mrCancel);
if CodeToolBoss.CheckLFM(fPascalBuffer, fLFMBuffer, fLFMTree,
fRootMustBeClassInUnit, fRootMustBeClassInIntf, fObjectsMustExist) then
Result:=mrOk
else begin
Result:=FindAndFixMissingComponentClasses;
if Result = mrCancel then // Returns mrCancel when nothing was done.
Result := mrOK;
end;
// Fix top offsets of some components in visual containers // Fix top offsets of some components in visual containers
if (Result=mrOK) and (fSettings.CoordOffsMode=rsEnabled) then begin
FormFileTool:=TFormFileConverter.Create(fCTLink, fLFMBuffer); FormFileTool:=TFormFileConverter.Create(fCTLink, fLFMBuffer);
SrcCoordOffs:=TObjectList.Create; SrcCoordOffs:=TObjectList.Create;
SrcNewProps:=TObjectList.Create; SrcNewProps:=TObjectList.Create;

View File

@ -49,10 +49,10 @@ type
TLFMChecker = class TLFMChecker = class
private private
fOnOutput: TOnAddFilteredLine; fOnOutput: TOnAddFilteredLine;
procedure WriteUnitError(Code: TCodeBuffer; X, Y: integer; procedure WriteUnitError(Code: TCodeBuffer; X, Y: integer; const ErrorMessage: string);
const ErrorMessage: string);
procedure WriteCodeToolsError; procedure WriteCodeToolsError;
function CheckUnit: boolean; function CheckUnit: boolean;
function ShowRepairLFMWizard: TModalResult; // Show the interactive user interface.
protected protected
fPascalBuffer: TCodeBuffer; fPascalBuffer: TCodeBuffer;
fLFMBuffer: TCodeBuffer; fLFMBuffer: TCodeBuffer;
@ -70,14 +70,13 @@ type
var StartPos, EndPos: integer); var StartPos, EndPos: integer);
function FindListBoxError: TLFMError; function FindListBoxError: TLFMError;
procedure WriteLFMErrors; procedure WriteLFMErrors;
function FixMissingComponentClasses: TModalResult; function FindAndFixMissingComponentClasses: TModalResult;
function FixMissingComponentClasses(aMissingTypes: TStringList): TModalResult; virtual;
procedure FillErrorsListBox; procedure FillErrorsListBox;
procedure JumpToError(LFMError: TLFMError); procedure JumpToError(LFMError: TLFMError);
procedure AddReplacement(LFMChangeList: TObjectList; StartPos, EndPos: integer; procedure AddReplacement(LFMChangeList: TObjectList; StartPos, EndPos: integer;
const NewText: string); const NewText: string);
function ApplyReplacements(LFMChangeList: TList): boolean; function ApplyReplacements(LFMChangeList: TList): boolean;
// Show the interactive user interface.
function ShowRepairLFMWizard: TModalResult; virtual;
public public
constructor Create(APascalBuffer, ALFMBuffer: TCodeBuffer; constructor Create(APascalBuffer, ALFMBuffer: TCodeBuffer;
const AOnOutput: TOnAddFilteredLine); const AOnOutput: TOnAddFilteredLine);
@ -426,7 +425,7 @@ begin
Result:=mrOk; Result:=mrOk;
exit; exit;
end; end;
Result:=FixMissingComponentClasses; Result:=FindAndFixMissingComponentClasses;
if Result in [mrAbort,mrOk] then exit; if Result in [mrAbort,mrOk] then exit;
WriteLFMErrors; WriteLFMErrors;
Result:=ShowRepairLFMWizard; Result:=ShowRepairLFMWizard;
@ -480,7 +479,7 @@ begin
Application.ProcessMessages; Application.ProcessMessages;
end; end;
function TLFMChecker.FixMissingComponentClasses: TModalResult; function TLFMChecker.FindAndFixMissingComponentClasses: TModalResult;
// returns true, if after adding units to uses section all errors are fixed // returns true, if after adding units to uses section all errors are fixed
var var
CurError: TLFMError; CurError: TLFMError;
@ -501,8 +500,7 @@ begin
MissingObjectTypes.Add(TypeName); MissingObjectTypes.Add(TypeName);
end; end;
CurError:=CurError.NextError; CurError:=CurError.NextError;
end; end; // Missing object types in unit.
// Missing object types in unit.
// keep all object types with a registered component class // keep all object types with a registered component class
for i:=MissingObjectTypes.Count-1 downto 0 do begin for i:=MissingObjectTypes.Count-1 downto 0 do begin
@ -513,9 +511,17 @@ begin
if MissingObjectTypes.Count=0 then exit; if MissingObjectTypes.Count=0 then exit;
// Missing object types, but luckily found in IDE. // Missing object types, but luckily found in IDE.
// there are missing object types with registered component classes Result:=FixMissingComponentClasses(MissingObjectTypes); // Fix them.
finally
MissingObjectTypes.Free;
end;
end;
function TLFMChecker.FixMissingComponentClasses(aMissingTypes: TStringList): TModalResult;
begin
// add units for the missing object types with registered component classes
Result:=PackageEditingInterface.AddUnitDependenciesForComponentClasses( Result:=PackageEditingInterface.AddUnitDependenciesForComponentClasses(
fPascalBuffer.Filename,MissingObjectTypes); fPascalBuffer.Filename, aMissingTypes);
if Result<>mrOk then exit; if Result<>mrOk then exit;
// check LFM again // check LFM again
@ -526,9 +532,6 @@ begin
end else begin end else begin
Result:=mrCancel; Result:=mrCancel;
end; end;
finally
MissingObjectTypes.Free;
end;
end; end;
function TLFMChecker.CheckUnit: boolean; function TLFMChecker.CheckUnit: boolean;
@ -537,7 +540,6 @@ var
NewX, NewY, NewTopLine: integer; NewX, NewY, NewTopLine: integer;
ErrorMsg: string; ErrorMsg: string;
MissingUnits: TStrings; MissingUnits: TStrings;
s: String;
begin begin
Result:=false; Result:=false;
// check syntax // check syntax
@ -555,8 +557,8 @@ begin
exit; exit;
end; end;
if (MissingUnits<>nil) and (MissingUnits.Count>0) then begin if (MissingUnits<>nil) and (MissingUnits.Count>0) then begin
s:=StringListToText(MissingUnits,','); ErrorMsg:=StringListToText(MissingUnits,',');
WriteUnitError(fPascalBuffer,1,1,'Units not found: '+s); WriteUnitError(fPascalBuffer,1,1,'Units not found: '+ErrorMsg);
exit; exit;
end; end;
finally finally
@ -704,7 +706,7 @@ begin
end; end;
end; end;
function TLFMChecker.ApplyReplacements(LfmChangeList: TList): boolean; function TLFMChecker.ApplyReplacements(LFMChangeList: TList): boolean;
var var
i: Integer; i: Integer;
Entry: TLFMChangeEntry; Entry: TLFMChangeEntry;