IDE: Guess ancestor type TFrame using heuristics. Issue #38585.

git-svn-id: trunk@64769 -
This commit is contained in:
juha 2021-03-09 09:11:14 +00:00
parent bddeba7ebf
commit 41c2e02039
3 changed files with 40 additions and 34 deletions

View File

@ -23,7 +23,7 @@ uses
// LCL // LCL
LCLMemManager, Forms, LResources, LCLMemManager, Forms, LResources,
// LazUtils // LazUtils
UITypes; UITypes, LazStringUtils;
type type
@ -45,7 +45,7 @@ type
out MissingClasses: TStrings// e.g. MyFrame2:TMyFrame out MissingClasses: TStrings// e.g. MyFrame2:TMyFrame
): TModalResult; virtual; abstract; ): TModalResult; virtual; abstract;
class function Priority: integer; virtual; // higher priority is tested first class function Priority: integer; virtual; // higher priority is tested first
class function DefaultComponentClass: TComponentClass; virtual; class function DefaultComponentClass(aClassName: string): TComponentClass; virtual;
class function FindComponentClass({%H-}aClassName: string): TComponentClass; virtual; class function FindComponentClass({%H-}aClassName: string): TComponentClass; virtual;
end; end;
TUnitResourcefileFormatClass = class of TUnitResourcefileFormat; TUnitResourcefileFormatClass = class of TUnitResourcefileFormat;
@ -62,7 +62,7 @@ type
class function GetClassNameFromStream(s: TStream; out IsInherited: Boolean): shortstring; override; class function GetClassNameFromStream(s: TStream; out IsInherited: Boolean): shortstring; override;
class function CreateReader(s: TStream; var DestroyDriver: boolean): TReader; override; class function CreateReader(s: TStream; var DestroyDriver: boolean): TReader; override;
class function CreateWriter(s: TStream; var DestroyDriver: boolean): TWriter; override; class function CreateWriter(s: TStream; var DestroyDriver: boolean): TWriter; override;
class function DefaultComponentClass: TComponentClass; override; class function DefaultComponentClass(aClassName: string): TComponentClass; override;
class function FindComponentClass(aClassName: string): TComponentClass; override; class function FindComponentClass(aClassName: string): TComponentClass; override;
end; end;
@ -150,9 +150,15 @@ begin
Result := CreateLRSWriter(s, DestroyDriver); Result := CreateLRSWriter(s, DestroyDriver);
end; end;
class function TCustomLFMUnitResourceFileFormat.DefaultComponentClass: TComponentClass; class function TCustomLFMUnitResourceFileFormat.DefaultComponentClass(
begin aClassName: string): TComponentClass;
Result := FormEditingHook.StandardDesignerBaseClasses[DesignerBaseClassId_TForm]; begin // Use heuristics to get a default class.
if PosI('DataModule',aClassName) > 0 then
Result:=FormEditingHook.StandardDesignerBaseClasses[DesignerBaseClassId_TDataModule]
else if PosI('Frame',aClassName) > 0 then
Result:=FormEditingHook.StandardDesignerBaseClasses[DesignerBaseClassId_TFrame]
else
Result := FormEditingHook.StandardDesignerBaseClasses[DesignerBaseClassId_TForm];
end; end;
class function TCustomLFMUnitResourceFileFormat.FindComponentClass( class function TCustomLFMUnitResourceFileFormat.FindComponentClass(
@ -175,7 +181,7 @@ begin
Result:=0; Result:=0;
end; end;
class function TUnitResourcefileFormat.DefaultComponentClass: TComponentClass; class function TUnitResourcefileFormat.DefaultComponentClass(aClassName: string): TComponentClass;
begin begin
Result:=TForm; Result:=TForm;
end; end;

View File

@ -56,7 +56,7 @@ uses
SourceSynEditor, SourceEditor, EditorOptions, EnvironmentOpts, CustomFormEditor, SourceSynEditor, SourceEditor, EditorOptions, EnvironmentOpts, CustomFormEditor,
ControlSelection, FormEditor, EmptyMethodsDlg, BaseDebugManager, TransferMacros, ControlSelection, FormEditor, EmptyMethodsDlg, BaseDebugManager, TransferMacros,
BuildManager, EditorMacroListViewer, FindRenameIdentifier, BuildModesManager, BuildManager, EditorMacroListViewer, FindRenameIdentifier, BuildModesManager,
ViewUnit_Dlg, InputHistory, CheckLFMDlg, etMessagesWnd, ViewUnit_Dlg, InputHistory, CheckLFMDlg, etMessagesWnd, UnitResources,
ConvCodeTool, BasePkgManager, PackageDefs, PackageSystem, Designer, DesignerProcs; ConvCodeTool, BasePkgManager, PackageDefs, PackageSystem, Designer, DesignerProcs;
type type
@ -6438,12 +6438,15 @@ function FindBaseComponentClass(AnUnitInfo: TUnitInfo; const AComponentClassName
DescendantClassName: string; out AComponentClass: TComponentClass): boolean; DescendantClassName: string; out AComponentClass: TComponentClass): boolean;
// returns false if an error occured // returns false if an error occured
// Important: returns true even if AComponentClass=nil // Important: returns true even if AComponentClass=nil
var
ResFormat: TUnitResourcefileFormatClass;
begin begin
AComponentClass:=nil; AComponentClass:=nil;
// find the ancestor class // find the ancestor class
if AnUnitInfo.UnitResourceFileformat<>nil then ResFormat:=AnUnitInfo.UnitResourceFileformat;
if ResFormat<>nil then
begin begin
AComponentClass:=AnUnitInfo.UnitResourceFileformat.FindComponentClass(AComponentClassName); AComponentClass:=ResFormat.FindComponentClass(AComponentClassName);
if AComponentClass<>nil then if AComponentClass<>nil then
exit(true); exit(true);
end; end;
@ -6481,9 +6484,10 @@ function LoadAncestorDependencyHidden(AnUnitInfo: TUnitInfo;
out AncestorClass: TComponentClass; out AncestorClass: TComponentClass;
out AncestorUnitInfo: TUnitInfo): TModalResult; out AncestorUnitInfo: TUnitInfo): TModalResult;
var var
AncsClsName, S: String; AncestorClsName, S: String;
CodeBuf: TCodeBuffer; CodeBuf: TCodeBuffer;
GrandAncestorClass, DefAncestorClass: TComponentClass; GrandAncestorClass, DefAncestorClass: TComponentClass;
ResFormat: TUnitResourcefileFormatClass;
begin begin
AncestorClass:=nil; AncestorClass:=nil;
AncestorUnitInfo:=nil; AncestorUnitInfo:=nil;
@ -6496,34 +6500,30 @@ begin
AnUnitInfo.Source:=CodeBuf; AnUnitInfo.Source:=CodeBuf;
end; end;
S:=aComponentClassName; if not CodeToolBoss.FindFormAncestor(AnUnitInfo.Source,aComponentClassName,
repeat AncestorClsName,true) then
if not CodeToolBoss.FindFormAncestor(AnUnitInfo.Source,S,AncsClsName,true) then DebugLn('LoadAncestorDependencyHidden Filename="',AnUnitInfo.Filename,'" ClassName=',aComponentClassName,
DebugLn('LoadAncestorDependencyHidden Filename="',AnUnitInfo.Filename,'" ClassName=',aComponentClassName, '. Unable to find ancestor class: ',CodeToolBoss.ErrorMessage);
'. Unable to find ancestor class: ',CodeToolBoss.ErrorMessage); // try the base designer classes
// try the base designer classes if not FindBaseComponentClass(AnUnitInfo,AncestorClsName,aComponentClassName,
if not FindBaseComponentClass(AnUnitInfo,AncsClsName,S,AncestorClass) then AncestorClass) then
begin begin
DebugLn(['LoadAncestorDependencyHidden FindUnitComponentClass failed for AncsClsName=',AncsClsName]); DebugLn(['LoadAncestorDependencyHidden FindUnitComponentClass failed for AncestorClsName=',AncestorClsName]);
exit(mrCancel); exit(mrCancel);
end; end;
S:=AncsClsName;
until Assigned(AncestorClass);
// try loading the ancestor first (unit, lfm and component instance) // try loading the ancestor first (unit, lfm and component instance)
if AnUnitInfo.UnitResourceFileformat<>nil then ResFormat:=AnUnitInfo.UnitResourceFileformat;
DefAncestorClass:=AnUnitInfo.UnitResourceFileformat.DefaultComponentClass if ResFormat<>nil then
DefAncestorClass:=ResFormat.DefaultComponentClass(aComponentClassName)
else else
DefAncestorClass:=nil;
// use TForm as default ancestor
if DefAncestorClass=nil then
DefAncestorClass:=BaseFormEditor1.StandardDesignerBaseClasses[DesignerBaseClassId_TForm]; DefAncestorClass:=BaseFormEditor1.StandardDesignerBaseClasses[DesignerBaseClassId_TForm];
if (AncestorClass=nil) then begin if (AncestorClass=nil) then begin
S:=''; S:='';
if DefAncestorClass<>nil then if DefAncestorClass<>nil then
S:=Format(lisIgnoreUseAsAncestor, [DefAncestorClass.ClassName]); S:=Format(lisIgnoreUseAsAncestor, [DefAncestorClass.ClassName]);
Result:=LoadComponentDependencyHidden(AnUnitInfo,AncsClsName,OpenFlags, Result:=LoadComponentDependencyHidden(AnUnitInfo,AncestorClsName,OpenFlags,
false,AncestorClass,AncestorUnitInfo,GrandAncestorClass,S); false,AncestorClass,AncestorUnitInfo,GrandAncestorClass,S);
if Result<>mrOk then begin if Result<>mrOk then begin
DebugLn(['LoadAncestorDependencyHidden DoLoadComponentDependencyHidden failed AnUnitInfo=',AnUnitInfo.Filename]); DebugLn(['LoadAncestorDependencyHidden DoLoadComponentDependencyHidden failed AnUnitInfo=',AnUnitInfo.Filename]);
@ -6540,7 +6540,7 @@ begin
end; end;
end; end;
//DebugLn('LoadAncestorDependencyHidden Filename="',AnUnitInfo.Filename,'" AncsClsName=',AncsClsName,' AncestorClass=',dbgsName(AncestorClass)); //DebugLn('LoadAncestorDependencyHidden Filename="',AnUnitInfo.Filename,'" AncestorClsName=',AncestorClsName,' AncestorClass=',dbgsName(AncestorClass));
if AncestorClass=nil then if AncestorClass=nil then
AncestorClass:=DefAncestorClass; AncestorClass:=DefAncestorClass;
Result:=mrOk; Result:=mrOk;
@ -7062,13 +7062,13 @@ begin
AComponentClass:=nil; AComponentClass:=nil;
Quiet:=([ofProjectLoading,ofQuiet]*Flags<>[]); Quiet:=([ofProjectLoading,ofQuiet]*Flags<>[]);
HideAbort:=not (ofProjectLoading in Flags); HideAbort:=not (ofProjectLoading in Flags);
{ Will be checked in FindComponentClass()
if not IsValidIdent(AComponentClassName) then if not IsValidIdent(AComponentClassName) then
begin begin
DebugLn(['LoadComponentDependencyHidden invalid component class name "',AComponentClassName,'"']); DebugLn(['LoadComponentDependencyHidden invalid component class name "',AComponentClassName,'"']);
exit(mrCancel); exit(mrCancel);
end; end;
}
// check for cycles // check for cycles
if AnUnitInfo.LoadingComponent then begin if AnUnitInfo.LoadingComponent then begin
Result:=IDEQuestionDialogAb(lisCodeTemplError, Result:=IDEQuestionDialogAb(lisCodeTemplError,

View File

@ -4453,7 +4453,7 @@ begin
try try
Result:=GetUnitsAndDepsForComps(ComponentClasses, Dependencies, UnitNames); Result:=GetUnitsAndDepsForComps(ComponentClasses, Dependencies, UnitNames);
if Result<>mrOk then exit; if Result<>mrOk then exit;
Assert(Assigned(UnitNames), 'TPkgManager.AddUnitDepsForCompClasses: UnitNames=Nil.');
if (Dependencies<>nil) then if (Dependencies<>nil) then
begin begin
Result:=FilterMissingDepsForUnit(UnitFilename,Dependencies,MissingDependencies); Result:=FilterMissingDepsForUnit(UnitFilename,Dependencies,MissingDependencies);