From dab39f77d5c3641afc1bbdebd56143d2420c2c40 Mon Sep 17 00:00:00 2001 From: Martin Date: Mon, 12 Feb 2024 01:21:40 +0100 Subject: [PATCH] Codetools: added test --- components/codetools/tests/laztests/tbar.pas | 15 ++ .../codetools/tests/laztests/tbar.unit1.pas | 21 +++ .../tests/laztests/tfoo.tproject1.pas | 128 ++++++++++++++++++ .../codetools/tests/laztests/tfoo.unit1.pas | 12 ++ .../tests/laztests/tproject1.unit1.pas | 20 +++ .../codetools/tests/testfinddeclaration.pas | 49 ++++--- 6 files changed, 229 insertions(+), 16 deletions(-) create mode 100644 components/codetools/tests/laztests/tbar.pas create mode 100644 components/codetools/tests/laztests/tbar.unit1.pas create mode 100644 components/codetools/tests/laztests/tfoo.tproject1.pas create mode 100644 components/codetools/tests/laztests/tfoo.unit1.pas create mode 100644 components/codetools/tests/laztests/tproject1.unit1.pas diff --git a/components/codetools/tests/laztests/tbar.pas b/components/codetools/tests/laztests/tbar.pas new file mode 100644 index 0000000000..14ee696d1d --- /dev/null +++ b/components/codetools/tests/laztests/tbar.pas @@ -0,0 +1,15 @@ +unit tbar; +{$mode ObjFPC}{$H+} +interface +type + bar = (xb1, xb2); + abc = (xa1, xa2); + + unit1 = (tbar_unit1_a, tbar_unit1_b); + project1 = (tbar_project1_a, tbar_project1_b); + tfoo = (tbar_tfoo_a, tbar_tfoo_b); + +implementation + +end. + diff --git a/components/codetools/tests/laztests/tbar.unit1.pas b/components/codetools/tests/laztests/tbar.unit1.pas new file mode 100644 index 0000000000..41907df10d --- /dev/null +++ b/components/codetools/tests/laztests/tbar.unit1.pas @@ -0,0 +1,21 @@ +unit tbar.Unit1; +{$mode ObjFPC}{$H+} +interface + +type + bar = (tbu1_b1, tbu1_b2); + abc = (tbu1_a1, tbu1_a2); + + unit1 = (tbu1__unit1_a, tbu1__unit1_b); + project1 = (tbu1__project1_a, tbu1__project1_b); + tfoo = (tbu1__tfoo_a, tbu1__tfoo_b); + + wrong_member_unit1 = (tbar_unit1_a, tbar_unit1_b); + wrong_member_project1 = (tbar_project1_a, tbar_project1_b); + wrong_member_tfoo = (tbar_tfoo_a, tbar_tfoo_b); + + +implementation + +end. + diff --git a/components/codetools/tests/laztests/tfoo.tproject1.pas b/components/codetools/tests/laztests/tfoo.tproject1.pas new file mode 100644 index 0000000000..20a25259d7 --- /dev/null +++ b/components/codetools/tests/laztests/tfoo.tproject1.pas @@ -0,0 +1,128 @@ +program tfoo.tproject1{findrefs:14,1;13,36;13,38;11,88;11,90;8,110;8,125;8,126}; +{$mode ObjFPC}{$ModeSwitch advancedrecords}{$H+} +uses + tproject1.unit1{declaration:tproject1.unit1/tproject1.unit1|completion:unit1,!tbar,!tfoo,!tsome|findrefs:6,89}, // TODO: findrefs missing 8,37 and 3,4 + tbar.unit1{declaration:tbar.unit1/tbar.unit1|completion:unit1,!tbar,!tfoo,!tsome|findrefs:}, // TODO: findrefs missing 3,5 + tfoo.unit1{declaration:tfoo.unit1/tfoo.unit1|completion:unit1,!tbar,!tfoo,!tsome|findrefs:8,23;8,33;8,34;8,36;8,38;6,85;6,86;6,88;6,90;34,105;34,106;3,110;3,125;3,126}, // TODO: findrefs WRONG too much: 8,36;8,38;6,88;6,90;3,110;3,125;3,126 + tbar{declaration:tbar/tbar|completion:+1=tbar,!tsome|findrefs:3,7;22,16;22,17;8,39;8,40;6,91;6,92}; + +var + v_u1: unit1{declaration:tbar/tbar.unit1|completion:+1=unit1}; + v_p1: project1{completion:+1=project1}; + tsome: integer; + +const + ref1_tbar_tfoo_a = tbar_tfoo_a{declaration:tbar/tbar.tfoo|completion:tbar_tfoo_a,tbar_tfoo_b}; + ref2_tbar_tfoo_a = tbar.tbar_tfoo_a{declaration:tbar/tbar.tfoo|completion:tbar_tfoo_a,tbar_tfoo_b,!u1,bar,abc}; + ref3_tbar_tfoo_a = tbar.tfoo{declaration:tbar/tbar.tfoo}.tbar_tfoo_a{declaration!:tbar/tbar.tfoo|completion:tbar_tfoo_a,tbar_tfoo_b,!u1,!bar,!abc,!unit1}; + +type + abc = (p1,p2); + + unit1{findrefs:3,22;23,36;9,54;8,56;41,59;16,70;3,72;3,73;11,76;3,80;6,87;21,88;9,93;11,119;3,123;3,124;18,125;18,126} = class // TODO: findrefs missing 11,41; WRONG/too much: 3,80 + x: tfoo.unit1.bar{declaration:tfoo.unit1/tfoo.unit1.bar|completion:bar,abc,u1,!unit1,!tfoo,!tproject1}; + unit1{findrefs:5,24;8,35;11,41;8,60;43,72;43,123;58,125}: record // TODO: WRONG 8,35;11,41 missing 3,80 + bar: (x_u1_b_a, x_u1_b_b); + end; static; + tproject1: record + bar: (x_p1_b_a, x_p1_b_b); + end; static; + type + abc = boolean; + public + b: tfoo.unit1.bar{declaration:tfoo.unit1/tfoo.unit1.bar|completion:bar,abc,u1,!unit1,!tfoo,!tproject1}; + c: tfoo.unit1.abc{declaration:tfoo.unit1/tfoo.unit1.abc|completion:bar,abc,u1,!unit1,!tfoo,!tproject1}; + d: unit1{ TODO: declaration:tfoo.tproject1/unit1}.abc{ TODO: declaration:tfoo.tproject1/unit1.abc|completion:x,unit1,tproject1,abc,!bar,!u1}; + e: tfoo.tproject1.unit1{declaration:tfoo.tproject1/unit1|completion:abc,unit1,!u1,!tfoo,!tbar,ref1_tbar_tfoo_a}.abc{declaration:tfoo.tproject1/unit1.abc|completion:abc,unit1,!u1,!tfoo,!tbar,!ref1_tbar_tfoo_a}; + f: tproject1.unit1.abc{ TODO declaration:tproject1.unit1/tproject1.unit1.abc|completion:bar,abc,!u1,unit1,!tfoo,!ref1_tbar_tfoo_a}; + g: tfoo.tproject1.abc{declaration:tfoo.tproject1/abc|completion:abc,unit1,!u1,!tfoo,!tbar,ref1_tbar_tfoo_a}; + h: tbar.abc{declaration:tbar/tbar.abc|completion:abc,unit1,!u1,!tbar,!ref1_tbar_tfoo_a}; + i: tbar.tfoo{declaration:tbar/tbar.tfoo|completion:abc,unit1,!u1,!tbar,!ref1_tbar_tfoo_a}; + v_u2: unit1{ TODO: declaration:tfoo.tproject1/unit1}; + + procedure M1; + public + tfoo: record + tproject1: (fp1, fp2); + end; + end; + + project1 =boolean; + +procedure bar; +var + tfoo: unit1{declaration:tfoo.tproject1/unit1}; + //tt: unit1; + bar: unit1.abc{declaration:tfoo.tproject1/unit1.abc}; + xyz: u1{declaration:tfoo.unit1/tfoo.unit1.u1}; +begin + tt{guesstype:tfoo.tproject1/unit1} := unit1{declaration:tfoo.tproject1/unit1}.Create{completion:create}; + tfoo.unit1{declaration:tfoo.tproject1/unit1.unit1}.bar{declaration:tfoo.tproject1/unit1.unit1.bar|completion:bar,!unit1,!tfoo,!abc} := x_u1_b_a{declaration!:tfoo.tproject1/unit1.unit1.bar|completion:x_u1_b_a,x_u1_b_b,!bar,!abc}; + tfoo.tproject1{declaration:tfoo.tproject1/unit1.tproject1}.bar{declaration:tfoo.tproject1/unit1.tproject1.bar} := x_p1_b_a{declaration!:tfoo.tproject1/unit1.tproject1.bar|completion:x_p1_b_a,x_p1_b_b,!x_u1_b_a,!x_u1_b_b,!bar,!abc}; + tfoo.b := fu1_b_a{declaration:tfoo.unit1/tfoo.unit1.bar}; + tfoo.c := fu1_a_a{declaration:tfoo.unit1/tfoo.unit1.abc}; + tfoo.d := true; + tfoo.e := true; + tfoo.f := a1{declaration:tproject1.unit1/tproject1.unit1.abc}; + tfoo.g := p1{declaration:tfoo.tproject1/abc}; + tfoo.h := xa1{declaration:tbar/tbar.abc}; + tfoo.i := tbar_tfoo_a{declaration:tbar/tbar.tfoo}; + tfoo.v_u2 := unit1.Create; + + unit1{declaration:tfoo.tproject1/unit1}.unit1{declaration:tfoo.tproject1/unit1.unit1}.bar{declaration:tfoo.tproject1/unit1.unit1.bar} := x_u1_b_a{declaration:tfoo.tproject1/unit1.unit1.bar}; + unit1{declaration:tfoo.tproject1/unit1}.tproject1{declaration:tfoo.tproject1/unit1.tproject1}.bar{declaration:tfoo.tproject1/unit1.tproject1.bar} := x_p1_b_a{declaration:tfoo.tproject1/unit1.tproject1.bar}; +end; + +procedure unit1.M1{declaration:tfoo.tproject1/unit1.M1}; +begin + tfoo{declaration:tfoo.tproject1/unit1.tfoo}.tproject1{declaration:tfoo.tproject1/unit1.tfoo.tproject1|completion:tproject1,!abc,!tfoo,!unit1} := fp1{declaration:tfoo.tproject1/unit1.tfoo.tproject1}; + + unit1{ TODO: declaration:tfoo.tproject1/unit1.unit1}.bar{ TODO: declaration:tfoo.tproject1/unit1.unit1.bar|completion:bar,!tproject1,!abc,!tfoo,!unit1} := x_u1_b_a{declaration:tfoo.tproject1/unit1.unit1.bar}; + tproject1{declaration:tfoo.tproject1/unit1.tproject1}.bar{declaration:tfoo.tproject1/unit1.tproject1.bar|completion:bar,!tproject1,!abc,!tfoo,!unit1} := x_p1_b_a{declaration:tfoo.tproject1/unit1.tproject1.bar}; +end; + +var + b: tfoo.unit1.bar{declaration:tfoo.unit1/tfoo.unit1.bar|completion:bar,abc,u1,!unit1,!tfoo,!tproject1}; + c: tfoo.unit1.abc{declaration:tfoo.unit1/tfoo.unit1.abc|completion:bar,abc,u1,!unit1,!tfoo,!tproject1}; + d: unit1{declaration:tfoo.tproject1/unit1}.abc{declaration:tfoo.tproject1/unit1.abc|completion:x,unit1,tproject1,abc,!bar,!u1}; + e: tfoo.tproject1.unit1{declaration:tfoo.tproject1/unit1|completion:abc,unit1,!u1,!tfoo,!tbar,ref1_tbar_tfoo_a}.abc{declaration:tfoo.tproject1/unit1.abc|completion:abc,unit1,!u1,!tfoo,!tbar,!ref1_tbar_tfoo_a}; + f: tproject1.unit1.abc{declaration:tproject1.unit1/tproject1.unit1.abc|completion:bar,abc,!u1,unit1,!tfoo,!ref1_tbar_tfoo_a}; + g: tfoo.tproject1.abc{declaration:tfoo.tproject1/abc|completion:abc,unit1,!u1,!tfoo,!tbar,ref1_tbar_tfoo_a}; + h: tbar.abc{declaration:tbar/tbar.abc|completion:abc,unit1,!u1,!tbar,!ref1_tbar_tfoo_a}; + i: tbar.tfoo{declaration:tbar/tbar.tfoo|completion:abc,unit1,!u1,!tbar,!ref1_tbar_tfoo_a}; + v_u2: unit1{declaration:tfoo.tproject1/unit1}; + v_p2: project1{declaration:tfoo.tproject1/project1}; +type + tbar=boolean; + {$SCOPEDENUMS On} + tproject1=(unit1, tbar); +var + h2: tbar; + j: tproject1; + +begin + b{guesstype:tfoo.unit1/bar} := fu1_b_a{declaration:tfoo.unit1/tfoo.unit1.bar}; + b{guesstype:tfoo.unit1/bar} := tfoo.unit1.bar.fu1_b_a{declaration!:tfoo.unit1/tfoo.unit1.bar}; + b{guesstype:tfoo.unit1/bar} := tfoo.unit1.fu1_b_a{declaration:tfoo.unit1/tfoo.unit1.bar}; + c := fu1_a_a{declaration:tfoo.unit1/tfoo.unit1.abc}; + d := true; + e := true; + tfoo.tproject1.bar{declaration:tfoo.tproject1/bar}; + f := a1{declaration:tproject1.unit1/tproject1.unit1.abc}; + g := p1{declaration:tfoo.tproject1/abc}; + h := xa1{declaration:tbar/tbar.abc}; + h2 := true; + i := tbar_tfoo_a{declaration:tbar/tbar.tfoo}; + j{guesstype:tfoo.tproject1/tproject1} := tproject1.unit1{declaration!:tfoo.tproject1/tproject1:98}; + j := tproject1.tbar{declaration!:tfoo.tproject1/tproject1:98}; + v_u1 := tbar_unit1_a{declaration:tbar/tbar.unit1}; + v_u2 := unit1{declaration:tfoo.tproject1/unit1}.Create; + v_p1 := tbar_project1_a{declaration:tbar/tbar.project1}; + v_p2 := true; + + unit1{declaration:tfoo.tproject1/unit1}.unit1{declaration:tfoo.tproject1/unit1.unit1}.bar{declaration:tfoo.tproject1/unit1.unit1.bar} := x_u1_b_a{declaration:tfoo.tproject1/unit1.unit1.bar}; + unit1{declaration:tfoo.tproject1/unit1}.tproject1{declaration:tfoo.tproject1/unit1.tproject1}.bar{declaration:tfoo.tproject1/unit1.tproject1.bar} := x_p1_b_a{declaration:tfoo.tproject1/unit1.tproject1.bar}; + tfoo.tproject1.unit1{declaration:tfoo.tproject1/unit1}.unit1{declaration:tfoo.tproject1/unit1.unit1}.bar{declaration:tfoo.tproject1/unit1.unit1.bar} := x_u1_b_a{declaration:tfoo.tproject1/unit1.unit1.bar}; + tfoo.tproject1.unit1{declaration:tfoo.tproject1/unit1}.tproject1{declaration:tfoo.tproject1/unit1.tproject1}.bar{declaration:tfoo.tproject1/unit1.tproject1.bar} := x_p1_b_a{declaration:tfoo.tproject1/unit1.tproject1.bar}; +end. + diff --git a/components/codetools/tests/laztests/tfoo.unit1.pas b/components/codetools/tests/laztests/tfoo.unit1.pas new file mode 100644 index 0000000000..709e871336 --- /dev/null +++ b/components/codetools/tests/laztests/tfoo.unit1.pas @@ -0,0 +1,12 @@ +unit tfoo.Unit1; +{$mode ObjFPC}{$H+} +interface +type + bar = (fu1_b_a, fu1_b_b); + abc = (fu1_a_a, fu1_a_b); + u1 = (fu1_u_a, fu1_u_b, tbar, unit1, project1); + +implementation + +end. + diff --git a/components/codetools/tests/laztests/tproject1.unit1.pas b/components/codetools/tests/laztests/tproject1.unit1.pas new file mode 100644 index 0000000000..659c24f3d9 --- /dev/null +++ b/components/codetools/tests/laztests/tproject1.unit1.pas @@ -0,0 +1,20 @@ +unit tproject1.Unit1; +{$mode ObjFPC}{$H+} +interface +type + bar = (b1, b2); + abc = (a1, a2); + + unit1 = (p1u1_unit1_a, p1u1_unit1_b); + project1 = (p1u1_project1_a, p1u1_project1_b); + tfoo = (p1u1_tfoo_a, p1u1_tfoo_b); + + wrong_member_unit1 = (tbar_unit1_a, tbar_unit1_b); + wrong_member_project1 = (tbar_project1_a, tbar_project1_b); + wrong_member_tfoo = (tbar_tfoo_a, tbar_tfoo_b); + + +implementation + +end. + diff --git a/components/codetools/tests/testfinddeclaration.pas b/components/codetools/tests/testfinddeclaration.pas index 198662f6b0..fa72064144 100644 --- a/components/codetools/tests/testfinddeclaration.pas +++ b/components/codetools/tests/testfinddeclaration.pas @@ -41,9 +41,11 @@ Each ENTRY can start with a ! to test for a non-present completion - {declaration: + {declaration:TEST + declaration!:TEST + TEST=[unitname/]nested.declaration.path[:linenumber] Tests: CodeToolBoss.FindDeclaration - Also runs {completion:*} + Also runs {completion:*} unless followed by ! {guesstype: Tests: CodeToolBoss.GuessTypeOfIdentifier @@ -294,7 +296,7 @@ var FoundNode: TCodeTreeNode; FoundPath: String; Src: String; - NameStartPos, i, l, IdentifierStartPos, IdentifierEndPos, + NameStartPos, i, j, l, IdentifierStartPos, IdentifierEndPos, BlockTopLine, BlockBottomLine, CommentEnd, StartOffs, TestLoop: Integer; Marker, ExpectedType, NewType, ExpexctedCompletion, ExpexctedTerm, ExpexctedCompletionPart, ExpexctedTermPart, s: String; @@ -365,12 +367,12 @@ begin end; CommentEnd := CommentP; - CommentP := p-1; + CommentP := p; repeat - NameStartPos:=CommentP+1; + NameStartPos:=CommentP; p := NameStartPos; - CommentP := PosEx('|', Src, NameStartPos); - if (CommentP < 1) or (CommentP > CommentEnd) then + CommentP := PosEx('|', Src, NameStartPos) + 1; + if (CommentP <= 1) or (CommentP > CommentEnd) then CommentP := CommentEnd; // check for specials: @@ -378,6 +380,7 @@ begin {guesstype:type} if not IsIdentStartChar[Src[p]] then continue; while (p<=length(Src)) and (IsIdentChar[Src[p]]) do inc(p); + if (p<=length(Src)) and (Src[p] = '!') then inc(p); Marker:=copy(Src,NameStartPos,p-NameStartPos); if (p>length(Src)) or (Src[p]<>':') then begin WriteSource(p,MainTool); @@ -388,13 +391,13 @@ begin PathPos:=p; //debugln(['TTestFindDeclaration.FindDeclarations Marker="',Marker,'" params: ',dbgstr(MainTool.Src,p,CommentP-p)]); - if (Marker='declaration') or (Marker='completion') then begin + if (Marker='declaration') or (Marker='declaration!') or (Marker='completion') then begin ExpectedPath:=copy(Src,PathPos,CommentP-1-PathPos); {$IFDEF VerboseFindDeclarationTests} debugln(['TTestFindDeclaration.FindDeclarations searching "',Marker,'" at ',MainTool.CleanPosToStr(NameStartPos-1),' ExpectedPath=',ExpectedPath]); {$ENDIF} - if (Marker='declaration') then begin + if (Marker='declaration') or (Marker='declaration!') then begin MainTool.CleanPosToCaret(IdentifierStartPos,CursorPos); // test FindDeclaration @@ -415,6 +418,18 @@ begin FoundTool:=CodeToolBoss.GetCodeToolForSource(FoundCursorPos.Code,true,true) as TFindDeclarationTool; FoundPath:=''; FoundNode:=nil; + i := pos('/', ExpectedPath); + if i > 1 then begin + FoundPath:=ExtractFileNameOnly(FoundCursorPos.Code.Filename); + AssertEquals('find declaration (Loop: '+IntToStr(TestLoop)+') FILENAME wrong at '+MainTool.CleanPosToStr(IdentifierStartPos,true),copy(LowerCase(ExpectedPath), 1 , i-1),LowerCase(FoundPath)); + delete(ExpectedPath, 1, i); + end; + i := pos(':', ExpectedPath); // line number + if i > 1 then begin + TryStrToInt(copy(ExpectedPath, i+1, Length(ExpectedPath)), j); + AssertEquals('find declaration (Loop: '+IntToStr(TestLoop)+') LINE wrong at '+MainTool.CleanPosToStr(IdentifierStartPos,true), j, FoundCursorPos.Y); + delete(ExpectedPath,i,Length(ExpectedPath)); + end; if (FoundCursorPos.Y=1) and (FoundCursorPos.X=1) then begin // unit FoundPath:=ExtractFileNameOnly(FoundCursorPos.Code.Filename); @@ -435,7 +450,7 @@ begin end; // test identifier completion - if (ExpectedPath<>'') then begin + if (ExpectedPath<>'') and (Marker<>'declaration!') then begin for ExpexctedCompletionPart in ExpectedPath.Split(';') do begin ExpexctedCompletion := ExpexctedCompletionPart; StartOffs := 0; @@ -506,6 +521,8 @@ begin continue; end else begin //debugln(['TTestFindDeclaration.FindDeclarations FoundPath=',FoundPath]); + if pos('/', ExpectedType) > 0 then + NewType := NewExprType.Context.Tool.GetSourceName + '/' + NewType; if LowerCase(ExpectedType)<>LowerCase(NewType) then begin WriteSource(IdentifierStartPos,MainTool); AssertEquals('GuessTypeOfIdentifier (Loop: '+IntToStr(TestLoop)+') wrong at '+MainTool.CleanPosToStr(IdentifierStartPos,true),LowerCase(ExpectedType),LowerCase(NewType)); @@ -522,7 +539,6 @@ begin ListOfPCodeXYPosition:=nil; Cache:=nil; MainTool.CleanPosToCaret(IdentifierStartPos,CursorPos); - if not CodeToolBoss.FindReferences( aCode,CursorPos.X,CursorPos.Y, aCode {TODO: iterate multiple files}, not ExpComment, @@ -531,11 +547,12 @@ begin AssertTrue('FindReferences failed at '+MainTool.CleanPosToStr(IdentifierStartPos,true), False); s := ''; - for i:=0 to ListOfPCodeXYPosition.Count-1 do begin - if s <> '' then - s := s + ';'; - s := s + IntToStr(PCodeXYPosition(ListOfPCodeXYPosition[i])^.X) + ',' + IntToStr(PCodeXYPosition(ListOfPCodeXYPosition[i])^.Y); - end; + if ListOfPCodeXYPosition <> nil then + for i:=0 to ListOfPCodeXYPosition.Count-1 do begin + if s <> '' then + s := s + ';'; + s := s + IntToStr(PCodeXYPosition(ListOfPCodeXYPosition[i])^.X) + ',' + IntToStr(PCodeXYPosition(ListOfPCodeXYPosition[i])^.Y); + end; CodeToolBoss.FreeListOfPCodeXYPosition(ListOfPCodeXYPosition); Cache.Free;