From 37d638661fabd2516582975a00607fa06b6c73db Mon Sep 17 00:00:00 2001 From: mattias Date: Tue, 11 Apr 2023 10:49:42 +0200 Subject: [PATCH] codetools: added GatherPublishedVarTypes, CompleteComponent with optional CheckUnits --- components/codetools/codetoolmanager.pas | 35 +-- components/codetools/eventcodetool.pas | 106 +++++++-- components/codetools/finddeclarationtool.pas | 1 - components/codetools/stdcodetools.pas | 94 ++++++++ .../tests/moduletests/dsgn_ambigbearbtn.pas | 20 ++ .../codetools/tests/runtestscodetools.lpi | 7 +- .../codetools/tests/runtestscodetools.lpr | 2 +- .../codetools/tests/testdesignerformtools.pas | 215 ++++++++++++++++-- ide/main.pp | 7 +- 9 files changed, 432 insertions(+), 55 deletions(-) create mode 100644 components/codetools/tests/moduletests/dsgn_ambigbearbtn.pas diff --git a/components/codetools/codetoolmanager.pas b/components/codetools/codetoolmanager.pas index 2704fa1006..94317660fc 100644 --- a/components/codetools/codetoolmanager.pas +++ b/components/codetools/codetoolmanager.pas @@ -834,13 +834,13 @@ type out AncestorClassName: string; DirtySearch: boolean): boolean; // form components - function AddPublishedVariables(Code: TCodeBuffer; - AComponent, AncestorComponent: TComponent): boolean; function CompleteComponent(Code: TCodeBuffer; - AComponent, AncestorComponent: TComponent): boolean; deprecated 'use AddPublishedVariables'; + AComponent, AncestorComponent: TComponent; CheckUnits: boolean): boolean; function PublishedVariableExists(Code: TCodeBuffer; const AClassName, AVarName: string; ErrorOnClassNotFound: boolean): boolean; + function GatherPublishedVarTypes(Code: TCodeBuffer; const AClassName: string; + out VarNameToType: TStringToStringTree): boolean; function AddPublishedVariable(Code: TCodeBuffer; const AClassName,VarName, VarType: string): boolean; function RemovePublishedVariable(Code: TCodeBuffer; @@ -5795,8 +5795,8 @@ begin end; end; -function TCodeToolManager.AddPublishedVariables(Code: TCodeBuffer; AComponent, - AncestorComponent: TComponent): boolean; +function TCodeToolManager.CompleteComponent(Code: TCodeBuffer; AComponent, + AncestorComponent: TComponent; CheckUnits: boolean): boolean; begin Result:=false; {$IFDEF CTDEBUG} @@ -5804,19 +5804,13 @@ begin {$ENDIF} if not InitCurCodeTool(Code) then exit; try - Result:=FCurCodeTool.AddPublishedVariables(AComponent,AncestorComponent, - SourceChangeCache); + Result:=FCurCodeTool.CompleteComponent(AComponent,AncestorComponent, + SourceChangeCache,CheckUnits); except on e: Exception do Result:=HandleException(e); end; end; -function TCodeToolManager.CompleteComponent(Code: TCodeBuffer; AComponent, - AncestorComponent: TComponent): boolean; -begin - Result:=AddPublishedVariables(Code,AComponent,AncestorComponent); -end; - function TCodeToolManager.PublishedVariableExists(Code: TCodeBuffer; const AClassName, AVarName: string; ErrorOnClassNotFound: boolean): boolean; begin @@ -5833,6 +5827,21 @@ begin end; end; +function TCodeToolManager.GatherPublishedVarTypes(Code: TCodeBuffer; + const AClassName: string; out VarNameToType: TStringToStringTree): boolean; +begin + Result:=false; + {$IFDEF CTDEBUG} + DebugLn('TCodeToolManager.GatherPublishedVarTypes A ',Code.Filename,' ',AClassName); + {$ENDIF} + if not InitCurCodeTool(Code) then exit; + try + Result:=FCurCodeTool.GatherPublishedVarTypes(AClassName,VarNameToType); + except + on e: Exception do Result:=HandleException(e); + end; +end; + function TCodeToolManager.AddPublishedVariable(Code: TCodeBuffer; const AClassName, VarName, VarType: string): boolean; begin diff --git a/components/codetools/eventcodetool.pas b/components/codetools/eventcodetool.pas index 872fde5f72..74d2baedb4 100644 --- a/components/codetools/eventcodetool.pas +++ b/components/codetools/eventcodetool.pas @@ -65,10 +65,8 @@ type function CollectPublishedMethods(Params: TFindDeclarationParams; const FoundContext: TFindContext): TIdentifierFoundResult; public - function AddPublishedVariables(AComponent, AncestorComponent: TComponent; - SourceChangeCache: TSourceChangeCache): boolean; function CompleteComponent(AComponent, AncestorComponent: TComponent; - SourceChangeCache: TSourceChangeCache): boolean; deprecated 'use AddPublishedVariables'; + SourceChangeCache: TSourceChangeCache; CheckUnits: boolean): boolean; function GetCompatiblePublishedMethods(const AClassName: string; PropInstance: TPersistent; const PropName: string; @@ -1372,20 +1370,74 @@ begin Result:=ifrProceedSearch; end; -function TEventsCodeTool.AddPublishedVariables(AComponent, - AncestorComponent: TComponent; SourceChangeCache: TSourceChangeCache - ): boolean; +function TEventsCodeTool.CompleteComponent(AComponent, + AncestorComponent: TComponent; SourceChangeCache: TSourceChangeCache; + CheckUnits: boolean): boolean; { - Adds all missing published variable declarations to the class definition in the source + - If CheckUnits=true then check used units for ambiguous classnames and add unitnames } +var + MissingClassTypes, ClassesNeedingUnitName: TFPList; // list of TComponentClass + + procedure CheckAmbiguity; + var + UsesNode, UseUnitNode: TCodeTreeNode; + AnUnitName, InFilename, CompClassName, CompUnitName, SourceName: string; + NewCodeTool: TFindDeclarationTool; + Params: TFindDeclarationParams; + i, NewTopLine, BlockTopLine, BlockBottomLine: integer; + aCompClass: TComponentClass; + NewPos: TCodeXYPosition; + begin + if MissingClassTypes.Count=0 then exit; + // search classtypes in used units + UsesNode:=FindMainUsesNode; + if UsesNode=nil then exit; + Params:=TFindDeclarationParams.Create(nil); + try + UseUnitNode:=UsesNode.LastChild; + while UseUnitNode<>nil do begin + AnUnitName:=ExtractUsedUnitName(UseUnitNode,@InFilename); + UseUnitNode:=UseUnitNode.PriorBrother; + if AnUnitName='' then continue; + NewCodeTool:=FindCodeToolForUsedUnit(AnUnitName,InFilename,false); + if NewCodeTool=nil then continue; + SourceName:=ExtractFileNameOnly(NewCodeTool.MainFilename); + + // search the classtypes in the interface of the used unit + for i:=0 to MissingClassTypes.Count-1 do begin + aCompClass:=TComponentClass(MissingClassTypes[i]); + if ClassesNeedingUnitName.IndexOf(aCompClass)>=0 then continue; + CompClassName:=aCompClass.ClassName; + CompUnitName:=aCompClass.UnitName; + if SameText(CompUnitName,SourceName) then + continue; // this is the unit of the component class + + if not NewCodeTool.FindDeclarationInInterface(CompClassName, + NewPos, NewTopLine, BlockTopLine, BlockBottomLine) then continue; + + // found component classtype in another unit -> needs unitname + ClassesNeedingUnitName.Add(aCompClass); + end; + end; + finally + Params.Free; + end; + end; + var i: Integer; CurComponent: TComponent; VarName, VarType: String; - UpperClassName, UpperCompName: String; + UpperClassName: String; + MissingComponents: TFPList; // list of TComponent begin + Result:=false; + ClassesNeedingUnitName:=TFPList.Create; + MissingComponents:=TFPList.Create; + MissingClassTypes:=TFPList.Create; try - Result:=false; ClearIgnoreErrorAfter; BuildTree(lsrImplementationStart); UpperClassName:=UpperCaseStr(AComponent.ClassName); @@ -1395,7 +1447,8 @@ begin // initialize class for code completion CodeCompleteClassNode:=FindClassNodeInInterface(UpperClassName,true,false,true); CodeCompleteSrcChgCache:=SourceChangeCache; - // complete all child components + + // collect all missing component variables for i:=0 to AComponent.ComponentCount-1 do begin CurComponent:=AComponent.Components[i]; {$IFDEF CTDEBUG} @@ -1404,15 +1457,28 @@ begin VarName:=CurComponent.Name; if VarName='' then continue; if (AncestorComponent<>nil) - and (AncestorComponent.FindComponent(VarName)<>nil) then continue; - UpperCompName:=UpperCaseStr(VarName); - VarType:=CurComponent.ClassName; + and (AncestorComponent.FindComponent(VarName)<>nil) then continue; // add missing published variable - if not VarExistsInCodeCompleteClass(UpperCompName) then begin - //DebugLn('[TEventsCodeTool.CompleteComponent] ADDING variable ',CurComponent.Name,':',CurComponent.ClassName); - AddClassInsertion(UpperCompName,VarName+':'+VarType+';',VarName,ncpPublishedVars); + if not VarExistsInCodeCompleteClass(UpperCaseStr(VarName)) then begin + MissingComponents.Add(CurComponent); + if MissingClassTypes.IndexOf(Pointer(CurComponent.ClassType))<0 then + MissingClassTypes.Add(CurComponent.ClassType); end; end; + + if CheckUnits then + CheckAmbiguity; + + // add component variable declarations + for i:=0 to MissingComponents.Count-1 do begin + CurComponent:=AComponent.Components[i]; + VarName:=CurComponent.Name; + VarType:=CurComponent.ClassName; + if ClassesNeedingUnitName.IndexOf(CurComponent.ClassType)>=0 then + VarType:=CurComponent.UnitName+'.'+VarType; + //DebugLn('[TEventsCodeTool.CompleteComponent] ADDING variable ',CurComponent.Name,':',CurComponent.ClassName); + AddClassInsertion(UpperCaseStr(VarName),VarName+':'+VarType+';',VarName,ncpPublishedVars); + end; {$IFDEF CTDEBUG} DebugLn('[TEventsCodeTool.CompleteComponent] invoke class completion'); {$ENDIF} @@ -1421,17 +1487,13 @@ begin DebugLn('[TEventsCodeTool.CompleteComponent] END'); {$ENDIF} finally + MissingClassTypes.Free; + MissingComponents.Free; + ClassesNeedingUnitName.Free; FreeClassInsertionList; end; end; -function TEventsCodeTool.CompleteComponent(AComponent, - AncestorComponent: TComponent; SourceChangeCache: TSourceChangeCache - ): boolean; -begin - Result:=AddPublishedVariables(AComponent,AncestorComponent,SourceChangeCache); -end; - function TEventsCodeTool.GetCompatiblePublishedMethods( const AClassName: string; PropInstance: TPersistent; const PropName: string; const Proc: TGetStrProc): boolean; diff --git a/components/codetools/finddeclarationtool.pas b/components/codetools/finddeclarationtool.pas index 8a0994067a..3d8efcc880 100644 --- a/components/codetools/finddeclarationtool.pas +++ b/components/codetools/finddeclarationtool.pas @@ -1108,7 +1108,6 @@ type FUnitName: string; FFound: Boolean; FResults: TStringList; - procedure Iterate(const AFilename: string); public constructor Create; diff --git a/components/codetools/stdcodetools.pas b/components/codetools/stdcodetools.pas index f769c74d2e..f50bdce508 100644 --- a/components/codetools/stdcodetools.pas +++ b/components/codetools/stdcodetools.pas @@ -225,6 +225,8 @@ type // published variables function FindPublishedVariable(const AClassName, AVarName: string; ExceptionOnClassNotFound: boolean): TCodeTreeNode; + function GatherPublishedVarTypes(const AClassName: string; + out VarNameToType: TStringToStringTree): boolean; function AddPublishedVariable(const AClassName,VarName, VarType: string; SourceChangeCache: TSourceChangeCache): boolean; virtual; function RemovePublishedVariable(const AClassName, AVarName: string; @@ -374,6 +376,7 @@ type SourceChangeCache: TSourceChangeCache; const Filter: TOnIDEDirectiveFilter = nil): boolean; + // debugging procedure CalcMemSize(Stats: TCTMemStats); override; end; @@ -4550,6 +4553,97 @@ begin end; end; +function TStandardCodeTool.GatherPublishedVarTypes(const AClassName: string; + out VarNameToType: TStringToStringTree): boolean; +var + ClassNode, SectionNode, Node, VarNode, TypeNode: TCodeTreeNode; + SimpleTypes: TStringToStringTree; + VarName, NewType, VarType, CurUnitName: String; + Params: TFindDeclarationParams; + aContext: TFindContext; +begin + Result:=true; + VarNameToType:=nil; + // search class + if (AClassName='') or (length(AClassName)>255) then + RaiseExceptionFmt(20230411091809,ctsinvalidClassName, [AClassName]); + BuildTree(lsrImplementationStart); + ClassNode:=FindClassNodeInInterface(AClassName,true,false,false); + if ClassNode=nil then + RaiseExceptionFmt(20230411091811,ctsclassNotFound, [AClassName]); + // traverse class declaration + SimpleTypes:=TStringToStringTree.Create(false); + try + SectionNode:=ClassNode.FirstChild; + while (SectionNode<>nil) do begin + if SectionNode.Desc=ctnClassPublished then begin + Node:=SectionNode.FirstChild; + while Node<>nil do begin + VarNode:=Node; + Node:=Node.NextBrother; + if (VarNode.Desc<>ctnVarDefinition) then continue; + // published variable + TypeNode:=FindTypeNodeOfDefinition(VarNode); + if TypeNode=nil then continue; + if TypeNode.Desc<>ctnIdentifier then continue; + // read variable name + VarName:=GetIdentifier(@Src[VarNode.StartPos]); + //debugln(['TStandardCodeTool.GatherPublishedVarTypes VarName="',VarName,'"']); + // read variable type + MoveCursorToNodeStart(TypeNode); + ReadNextAtom; + if not AtomIsIdentifier then + continue; + VarType:=GetAtom; + while ReadNextAtomIs('.') do begin + ReadNextAtom; + if not AtomIsIdentifier then + break; + VarType:=VarType+'.'+GetAtom; + end; + //debugln(['TStandardCodeTool.GatherPublishedVarTypes VarType="',VarType,'"']); + if (CurPos.Flag<>cafSemicolon) then begin + //debugln(['TStandardCodeTool.GatherPublishedVarTypes WARNING not a simple type: ',VarName]); + continue; // e.g. specialize A + end; + if (Pos('.',VarType)<1) then begin + // simple type without unitname + NewType:=SimpleTypes[VarType]; + if NewType='' then + begin + // resolve simple type + Params:=TFindDeclarationParams.Create; + try + Params.ContextNode:=TypeNode; + // resolve alias + aContext:=FindBaseTypeOfNode(Params,TypeNode); + //debugln(['TStandardCodeTool.GatherPublishedVarTypes Type "',VarType,'" found at ',FindContextToString(aContext,false)]); + if aContext.Node.Desc=ctnClass then + VarType:=aContext.Tool.ExtractClassName(aContext.Node,false); + CurUnitName:=aContext.Tool.GetSourceName(false); + // unitname.vartype + NewType:=CurUnitName+'.'+VarType; + //debugln(['TStandardCodeTool.GatherPublishedVarTypes Resolved: "',VarType,'" = "',NewType,'"']); + SimpleTypes[VarType]:=NewType; + finally + Params.Free; + end; + end; + VarType:=NewType; + end; + //debugln(['TStandardCodeTool.GatherPublishedVarTypes Added ',VarName,':',VarType]); + if VarNameToType=nil then + VarNameToType:=TStringToStringTree.Create(false); + VarNameToType[VarName]:=VarType; + end; + end; + SectionNode:=SectionNode.NextBrother; + end; + finally + SimpleTypes.Free; + end; +end; + function TStandardCodeTool.AddPublishedVariable(const AClassName, VarName, VarType: string; SourceChangeCache: TSourceChangeCache): boolean; var ClassNode, SectionNode: TCodeTreeNode; diff --git a/components/codetools/tests/moduletests/dsgn_ambigbearbtn.pas b/components/codetools/tests/moduletests/dsgn_ambigbearbtn.pas new file mode 100644 index 0000000000..e05a921724 --- /dev/null +++ b/components/codetools/tests/moduletests/dsgn_ambigbearbtn.pas @@ -0,0 +1,20 @@ +unit Dsgn_AmbigBearBtn; + +{$mode ObjFPC}{$H+} + +interface + +uses + Classes, SysUtils; + +type + + { TBearButton } + + TBearButton = class(TComponent) + end; + +implementation + +end. + diff --git a/components/codetools/tests/runtestscodetools.lpi b/components/codetools/tests/runtestscodetools.lpi index 646eafa00e..4f6f853131 100644 --- a/components/codetools/tests/runtestscodetools.lpi +++ b/components/codetools/tests/runtestscodetools.lpi @@ -37,7 +37,7 @@ - + @@ -134,6 +134,11 @@ + + + + + diff --git a/components/codetools/tests/runtestscodetools.lpr b/components/codetools/tests/runtestscodetools.lpr index 7178a15c9c..9714df346c 100644 --- a/components/codetools/tests/runtestscodetools.lpr +++ b/components/codetools/tests/runtestscodetools.lpr @@ -40,7 +40,7 @@ uses TestStdCodetools, TestFindDeclaration, TestIdentCompletion, TestCompleteBlock, TestRefactoring, TestCodeCompletion, TestCompReaderWriterPas, fdt_arrays, TestCTPas2js, TestChangeDeclaration, TestLFMTrees, - TestDesignerFormTools, Dsgn_BearButtons; + TestDesignerFormTools, Dsgn_BearButtons, Dsgn_AmbigBearBtn; const ConfigFilename = 'codetools.config'; diff --git a/components/codetools/tests/testdesignerformtools.pas b/components/codetools/tests/testdesignerformtools.pas index 91e6c02ab5..986725dcd8 100644 --- a/components/codetools/tests/testdesignerformtools.pas +++ b/components/codetools/tests/testdesignerformtools.pas @@ -6,8 +6,9 @@ interface uses Classes, SysUtils, CodeToolManager, CodeCache, DefineTemplates, - LazLogger, LazFileUtils, fpcunit, testregistry, - TestFinddeclaration, TestStdCodetools, Dsgn_BearControls, Dsgn_BearButtons; + LazLogger, LazFileUtils, AvgLvlTree, Laz_AVL_Tree, fpcunit, testregistry, + TestFinddeclaration, TestStdCodetools, + Dsgn_AmbigBearBtn, Dsgn_BearControls, Dsgn_BearButtons; type TBearForm1 = class(TBearForm) @@ -17,8 +18,8 @@ type TTestDesignerFormTools = class(TCustomTestCTStdCodetools) private - procedure TestAddPublishedBearVars(Title: string; Src: array of string; - Expected: array of string); + procedure TestCompleteComponent(const Title: string; CheckUnits: boolean; const Src, Expected: array of string); + procedure TestGatherPublishedVarType(const Title, aClassName: string; const Src, ExpectedVars: array of string); protected procedure SetUp; override; procedure TearDown; override; @@ -28,14 +29,20 @@ type // add published variables procedure TestAddPublishedVariables_Empty; procedure TestAddPublishedVariables_Button1; + procedure TestAddPublishedVariables_AmbiguousButtons1; + procedure TestAddPublishedVariables_AmbiguousButtons2; + // gather published variable types + procedure TestGatherPublishedVarTypes_Empty; + procedure TestGatherPublishedVarTypes_Button1; + procedure TestGatherPublishedVarTypes_Button2; end; implementation { TTestDesignerFormTools } -procedure TTestDesignerFormTools.TestAddPublishedBearVars(Title: string; - Src: array of string; Expected: array of string); +procedure TTestDesignerFormTools.TestCompleteComponent(const Title: string; + CheckUnits: boolean; const Src, Expected: array of string); var i, NewX, NewY: Integer; s, Dir: String; @@ -53,9 +60,7 @@ begin try CodeToolBoss.DefineTree.Add(DefTemp); - //debugln(['TTestFindDeclaration.TestFindDeclaration_UnitSearch_CurrentDir ',CodeToolBoss.GetUnitPathForDirectory('')]); - - if not CodeToolBoss.AddPublishedVariables(Code,BearForm1,nil) + if not CodeToolBoss.CompleteComponent(Code,BearForm1,nil,CheckUnits) and (CodeToolBoss.ErrorDbgMsg<>'') then begin NewCode:=Code; @@ -67,7 +72,7 @@ begin NewCode:=CodeToolBoss.ErrorCode; end; WriteSource(NewCode.Filename,NewY,NewX); - Fail(Title+': call CompleteCode failed: "'+CodeToolBoss.ErrorDbgMsg+'"'); + Fail(Title+': call CompleteComponent failed: "'+CodeToolBoss.ErrorDbgMsg+'"'); end; s:=''; for i:=Low(Expected) to High(Expected) do @@ -78,6 +83,63 @@ begin end; end; +procedure TTestDesignerFormTools.TestGatherPublishedVarType(const Title, + aClassName: string; const Src, ExpectedVars: array of string); +var + Code, NewCode: TCodeBuffer; + VarNameToToType: TStringToStringTree; + Expected, Actual, Dir: String; + i, NewY, NewX: Integer; + DefTemp: TDefineTemplate; +begin + Code:=CodeToolBoss.CreateFile('test1.pas'); + Actual:=''; + for i:=Low(Src) to High(Src) do + Actual+=Src[i]+LineEnding; + Code.Source:=Actual; + + Dir:=AppendPathDelim(GetCurrentDir)+'moduletests'; + DefTemp:=TDefineTemplate.Create('unitpath','add moduletests',UnitPathMacroName,Dir,da_Define); + VarNameToToType:=nil; + try + CodeToolBoss.DefineTree.Add(DefTemp); + + if not CodeToolBoss.GatherPublishedVarTypes(Code,aClassName,VarNameToToType) + and (CodeToolBoss.ErrorDbgMsg<>'') then + begin + NewCode:=Code; + NewY:=1; + NewX:=1; + if (CodeToolBoss.ErrorCode<>nil) and (CodeToolBoss.ErrorLine>0) then begin + NewY:=CodeToolBoss.ErrorLine; + NewX:=CodeToolBoss.ErrorColumn; + NewCode:=CodeToolBoss.ErrorCode; + end; + WriteSource(NewCode.Filename,NewY,NewX); + Fail(Title+': call GatherPublishedVarTypes failed: "'+CodeToolBoss.ErrorDbgMsg+'"'); + end; + + Actual:=''; + if VarNameToToType<>nil then begin + Actual:=VarNameToToType.AsText; + Actual:=StringReplace(Actual,'=',':',[rfReplaceAll]); + end; + Expected:=''; + for i:=Low(ExpectedVars) to High(ExpectedVars) do + Expected+=ExpectedVars[i]+LineEnding; + if Actual<>Expected then begin + debugln(['TTestDesignerFormTools.TestGatherPublishedVarType Expected:']); + debugln(Expected); + debugln(['TTestDesignerFormTools.TestGatherPublishedVarType Actual:']); + debugln(Actual); + Fail('VarNameToToType differ'); + end; + finally + VarNameToToType.Free; + CodeToolBoss.DefineTree.RemoveDefineTemplate(DefTemp); + end; +end; + procedure TTestDesignerFormTools.SetUp; begin inherited SetUp; @@ -92,7 +154,7 @@ end; procedure TTestDesignerFormTools.TestAddPublishedVariables_Empty; begin - TestAddPublishedBearVars('TestAddPublishedVariables_Empty', + TestCompleteComponent('TestAddPublishedVariables_Empty',true, ['unit test1;' ,'{$mode objfpc}{$H+}' ,'interface' @@ -116,12 +178,12 @@ end; procedure TTestDesignerFormTools.TestAddPublishedVariables_Button1; var - Btn: TBearButton; + Btn: Dsgn_BearButtons.TBearButton; begin - Btn:=TBearButton.Create(BearForm1); + Btn:=Dsgn_BearButtons.TBearButton.Create(BearForm1); Btn.Name:='Button1'; - TestAddPublishedBearVars('TestAddPublishedVariables_Empty', + TestCompleteComponent('TestAddPublishedVariables_Button1',true, ['unit test1;' ,'{$mode objfpc}{$H+}' ,'interface' @@ -144,6 +206,131 @@ begin ,'end.']); end; +procedure TTestDesignerFormTools.TestAddPublishedVariables_AmbiguousButtons1; +var + Btn1: Dsgn_BearButtons.TBearButton; +begin + Btn1:=Dsgn_BearButtons.TBearButton.Create(BearForm1); + Btn1.Name:='Button1'; + + TestCompleteComponent('TestAddPublishedVariables_AmbiguousButtons1',true, + ['unit test1;' + ,'{$mode objfpc}{$H+}' + ,'interface' + ,'uses Dsgn_BearControls, Dsgn_BearButtons, Dsgn_AmbigBearBtn;' + ,'type' + ,' TBearForm1 = class(TBearForm)' + ,' end;' + ,'implementation' + ,'end.'], + ['unit test1;' + ,'{$mode objfpc}{$H+}' + ,'interface' + ,'uses Dsgn_BearControls, Dsgn_BearButtons, Dsgn_AmbigBearBtn;' + ,'type' + ,' { TBearForm1 }' + ,' TBearForm1 = class(TBearForm)' + ,' Button1: Dsgn_BearButtons.TBearButton;' + ,' end;' + ,'implementation' + ,'end.']); +end; + +procedure TTestDesignerFormTools.TestAddPublishedVariables_AmbiguousButtons2; +var + Btn1: Dsgn_BearButtons.TBearButton; + Btn2: Dsgn_AmbigBearBtn.TBearButton; + Label1: TBearLabel; +begin + Btn1:=Dsgn_BearButtons.TBearButton.Create(BearForm1); + Btn1.Name:='Button1'; + Btn2:=Dsgn_AmbigBearBtn.TBearButton.Create(BearForm1); + Btn2.Name:='Button2'; + Label1:=TBearLabel.Create(BearForm1); + Label1.Name:='Label1'; + + TestCompleteComponent('TestAddPublishedVariables_AmbiguousButtons2',true, + ['unit test1;' + ,'{$mode objfpc}{$H+}' + ,'interface' + ,'uses Dsgn_BearControls, Dsgn_BearButtons, Dsgn_AmbigBearBtn;' + ,'type' + ,' TBearForm1 = class(TBearForm)' + ,' end;' + ,'implementation' + ,'end.'], + ['unit test1;' + ,'{$mode objfpc}{$H+}' + ,'interface' + ,'uses Dsgn_BearControls, Dsgn_BearButtons, Dsgn_AmbigBearBtn;' + ,'type' + ,' { TBearForm1 }' + ,' TBearForm1 = class(TBearForm)' + ,' Button1: Dsgn_BearButtons.TBearButton;' + ,' Button2: Dsgn_AmbigBearBtn.TBearButton;' + ,' Label1: TBearLabel;' + ,' end;' + ,'implementation' + ,'end.']); +end; + +procedure TTestDesignerFormTools.TestGatherPublishedVarTypes_Empty; +begin + TestGatherPublishedVarType('TestGatherPublishedVarTypes_Empty', + 'TBearForm1', + ['unit test1;' + ,'{$mode objfpc}{$H+}' + ,'interface' + ,'uses Dsgn_BearControls, Dsgn_BearButtons, Dsgn_AmbigBearBtn;' + ,'type' + ,' TBearForm1 = class(TBearForm)' + ,' end;' + ,'implementation' + ,'end.'], + [] + ); +end; + +procedure TTestDesignerFormTools.TestGatherPublishedVarTypes_Button1; +begin + TestGatherPublishedVarType('TestGatherPublishedVarTypes_Empty', + 'TBearForm1', + ['unit test1;' + ,'{$mode objfpc}{$H+}' + ,'interface' + ,'uses Dsgn_BearControls, Dsgn_BearButtons, Dsgn_AmbigBearBtn;' + ,'type' + ,' TBearForm1 = class(TBearForm)' + ,' Button1: TBearButton;' + ,' end;' + ,'implementation' + ,'end.'], + ['Button1:Dsgn_AmbigBearBtn.TBearButton'] + ); +end; + +procedure TTestDesignerFormTools.TestGatherPublishedVarTypes_Button2; +begin + TestGatherPublishedVarType('TestGatherPublishedVarTypes_Empty', + 'TBearForm1', + ['unit test1;' + ,'{$mode objfpc}{$H+}' + ,'interface' + ,'uses Dsgn_BearControls, Dsgn_BearButtons, Dsgn_AmbigBearBtn;' + ,'type' + ,' TBearForm1 = class(TBearForm)' + ,' Button1: TBearButton;' + ,' Button2: Dsgn_BearButtons.TBearButton;' + ,' Label1: TBearLabel;' + ,' end;' + ,'implementation' + ,'end.'], + ['Button1:Dsgn_AmbigBearBtn.TBearButton', + 'Button2:Dsgn_BearButtons.TBearButton', + 'Label1:Dsgn_BearControls.TBearLabel'] + ); +end; + initialization RegisterTests([TTestDesignerFormTools]); diff --git a/ide/main.pp b/ide/main.pp index ce302c46bf..be5c0223ec 100644 --- a/ide/main.pp +++ b/ide/main.pp @@ -12388,7 +12388,7 @@ var Ancestor: TComponent; AnUnitInfo: TUnitInfo; AnIDesigner: TIDesigner; - HasResources: Boolean; + HasResources, CheckUnits: Boolean; FileItem: PStringToStringItem; begin GetDefaultProcessList.FreeStoppedProcesses; @@ -12403,8 +12403,9 @@ begin SourceEditorManager.AddJumpPointClicked(Self); // Add component definitions to form's source code Ancestor:=GetAncestorLookupRoot(FComponentAddedUnit); - CodeToolBoss.AddPublishedVariables(FComponentAddedUnit.Source, - FComponentAddedDesigner.LookupRoot, Ancestor); + CheckUnits:=false; + CodeToolBoss.CompleteComponent(FComponentAddedUnit.Source, + FComponentAddedDesigner.LookupRoot, Ancestor, CheckUnits); FComponentAddedDesigner:=nil; end;