Codetools: more tests for ampersand.

This commit is contained in:
Martin 2024-09-03 15:46:06 +02:00
parent 8f49ff3eaa
commit 35c1846863
4 changed files with 282 additions and 3 deletions

View File

@ -0,0 +1,25 @@
unit &procedure;
{$mode ObjFPC}{$H+}
interface
type
{$ScopedEnums on}
&var = (&array, &end, foo, &bar);
{$ScopedEnums off}
&end = array of (&abc, def, &uses,new);
&interface = set of (&set, &_);
function other(&type: &var; &begin: &end): &interface;
function more(&type: &procedure.&var; &begin: &procedure.&end): &procedure.&interface;
implementation
function other(&type: &var; &begin: &end): &interface;
begin
end;
function more(&type: &procedure.&var; &begin: &procedure.&end): &procedure.&interface;
begin
end;
end.

View File

@ -0,0 +1,177 @@
program &tampersand{ TODO findrefs:0,0};
{$mode ObjFPC}{$H+}
uses
&procedure {completion:procedure|completion:-1=procedure|completion:+1=procedure|declaration:procedure/procedure}
;
type
xyz = integer;
&var{declaration:procedure/&procedure.var} // previous declaration
=
(&array{declaration:tampersand/var},
&begin{declaration:tampersand/var},
foo{declaration:tampersand/var},
&bar{declaration:tampersand/var}
);
&end{declaration:procedure/&procedure.end} // previous declaration
=
array of (&abc{declaration:tampersand/end},
def{declaration:tampersand/end},
&uses{declaration:tampersand/end}
);
&program =
set of (&set{declaration:tampersand/program},
&_{declaration:tampersand/program}
);
&for = boolean;
&if =
class
public type
&for{declaration:tampersand/for} // previous declaration
= integer;
end;
&record = record
abc:
integer;
&array:
record
x,y,&case:
&if{declaration:tampersand/if}.&for{completion:&for|completion:-1=&for|declaration:tampersand/if.for};
end
end;
function &function(
&type: &var{completion:&var,xyz|completion:-1=&var,xyz|declaration:tampersand/var};
&begin: &end{declaration:tampersand/end}
): &program{completion:&program,xyz|completion:-1=&program,xyz|declaration:tampersand/program};
var
&then: &var;
&if: &program;
begin
&then {guesstype:&tampersand/var}
:= &type;
&if{guesstype:&tampersand/program}
:= &result;
end;
function fun(
&type: &tampersand.&var{completion:&var,xyz|completion:-1=&var,xyz|declaration:tampersand/var};
&begin: tampersand.&end{declaration:tampersand/end}
): &tampersand{completion:&tampersand,&program,xyz|completion:-1=&tampersand,&program,xyz|declaration!:tampersand}
.&program{completion:&program,xyz|completion:-1=&program,xyz|declaration:tampersand/program};
var
&then: &var;
&if: &program;
begin
&then {guesstype:&tampersand/var}
:= &type;
&if{guesstype:&tampersand/program}
:= &result;
end;
function &name(
&type: &procedure.&var{declaration:procedure/&procedure.var};
&begin: &procedure.&end{declaration:procedure/&procedure.end}
): &procedure.&interface{declaration!:procedure/&procedure.interface};
var
&then: &procedure.&var;
&if: &procedure.&interface;
begin
&then {guesstype:&procedure/var}
:= &type;
&if{guesstype:&procedure/interface}
:= &result;
end;
var
&class:
&program{completion:&tampersand,&program,xyz|completion:-1=&tampersand,&program,xyz|declaration:tampersand/program};
fun1:
&tampersand.&program{declaration:tampersand/program};
fun2:
&program{declaration:tampersand/program};
n1, n2:
&procedure.&interface{declaration!:procedure/&procedure.interface};
&const:
&end{declaration:tampersand/end};
&case, cast:
&record{declaration:tampersand/record};
&then:
integer;
begin
&class{guesstype:&tampersand/program}
:=
&function{completion:&tampersand,&function,fun,&program,xyz|completion:-1=&tampersand,&function,fun,&program,xyz|completion:+11=&function,fun,!&program,!program,!xyz|declaration!:tampersand/&function}
(&array{completion:&tampersand,&function,fun,&array,xyz|completion:-1=&tampersand,&function,fun,&array,xyz|completion:+1=!&function,!function,!fun,&array,!xyz|declaration!:tampersand/var},
&const
);
fun1
:=
&fun{completion:&tampersand,&function,fun,&program,xyz|completion:-1=&tampersand,&function,fun,&program,xyz|completion:+11=&function,fun,!&program,!program,!xyz|declaration!:tampersand/fun}
(
&var.&begin,
[&tampersand.&uses, &uses]
);
fun2
:=
fun(
&foo,
[def, &def, abc, &abc]
);
&name(
&procedure.&var.&foo,
[&procedure.&def]
);
name(
&procedure.&var.foo,
[&procedure.def]
);
n1
:=
&other{completion:&procedure,&tampersand,other,more,&program,xyz|completion:-1=&procedure,&tampersand,other,more,&program,xyz|completion:+11=other|declaration!:procedure/&procedure.other}
(
&procedure.&var.&end,
[&procedure.def]
);
n2
:=
other(
&procedure.&var.&end,
[&procedure.&def]
);
&more(
&procedure.&var.&foo,
[new]
);
cast{completion:&case,cast,n1|completion:-1=&case,cast,n1|completion:+1=&case,&const,!then,!&then}.
abc :=&2;
cast.&abc :=2;
cast.&array:=&case.&array;
cast.&array.x:=2;
cast.&array.&case:=2;
&cast{completion:&case,cast,n1|completion:-1=&case,cast,n1|completion:+1=&case,&const,!then,!&then}.
abc :=2;
&cast.&abc :=2;
&cast.&array:=&case.&array;
&cast.&array.x:=2;
&cast.&array.&case:=2;
&case.abc :=2;
&case.&abc :=&2;
&case.&array:=cast.&array;
&case.&array.x:=2;
&then { TODO: guesstype:tampersand/if.for}
:=
&case{completion:&case|completion:-1=&case|completion:+1=&case,&const,!then,!&then}.
&array{completion:&array,abc|completion:-1=&array,abc|completion:+1=&array,abc|completion:+2=&array,!abc|declaration:tampersand/record.array}.
&case{completion:&case,x,y|completion:-1=&case,x,y|completion:+1=&case,!x,!y|declaration:tampersand/record.array.case}
;
end.

View File

@ -38,6 +38,7 @@
Each TEST can start with an optional POS (integer positive/negative)
The POS specifies the relative source-pos from the start of the identifier before the comment.
("start of the identifier": identifier does NOT include any "&" for this pos)
Each ENTRY can start with a ! to test for a non-present completion
@ -484,9 +485,14 @@ begin
while i>=0 do begin
IdentItem:=CodeToolBoss.IdentifierList.FilteredItems[i];
//debugln(['TTestFindDeclaration.FindDeclarations ',IdentItem.Identifier]);
l:=length(IdentItem.Identifier);
s := IdentItem.Identifier;
if (iliNeedsAmpersand in IdentItem.Flags)
and (Marker = 'completion') // declaration=path.ident does not include the &
then
s := '&' + s;
l:=length(s);
if ((l=length(ExpexctedTerm)) or (ExpexctedTerm[length(ExpexctedTerm)-l]='.'))
and (CompareText(IdentItem.Identifier,RightStr(ExpexctedTerm,l))=0)
and (CompareText(s,RightStr(ExpexctedTerm,l))=0)
then break;
dec(i);
end;
@ -523,7 +529,10 @@ begin
end else begin
//debugln(['TTestFindDeclaration.FindDeclarations FoundPath=',FoundPath]);
if pos('/', ExpectedType) > 0 then
NewType := NewExprType.Context.Tool.GetSourceName + '/' + NewType;
if NewExprType.Context.Tool <> nil then
NewType := NewExprType.Context.Tool.GetSourceName + '/' + NewType
else
NewType := 'NOT-FOUND' + '/' + 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));

View File

@ -43,7 +43,9 @@ type
);
published
procedure Test_GetValuesOfCaseVariable_Enum;
procedure Test_GetValuesOfCaseVariable_Enum_Amp;
procedure Test_FindCodeContext_ProcParams;
procedure Test_FindCodeContext_ProcParams_Amp;
procedure Test_FindCodeContext_ProcParams_NoClosingBracket;
procedure Test_FindCodeContext_ProcTypeParams;
procedure Test_FindCodeContext_AttributeParams;
@ -96,6 +98,33 @@ begin
end;
end;
procedure TTestIdentCompletion.Test_GetValuesOfCaseVariable_Enum_Amp;
var
List: TStrings;
begin
List:=TStringList.Create;
try
Code.Source:=
'type &array = (abc, &array, amp, &aaa);'+LineEnding
+'var e: &array;'+LineEnding
+'begin'+LineEnding
+' case e of'+LineEnding
+'end.';
List.Clear;
if not CodeToolBoss.GetValuesOfCaseVariable(Code,8,4,List) then begin
Fail('GetValuesOfCaseVariable failed on case enum');
end;
//writeln('TTestIdentCompletion.Test_GetValuesOfCaseVariable_Enum ',List.Text);
AssertEquals('case enum count',4,List.Count);
AssertEquals('case enum[0]','abc',List[0]);
AssertEquals('case enum[1]','&array',List[1]);
AssertEquals('case enum[2]','amp',List[2]);
AssertEquals('case enum[3]','&aaa',List[3]);
finally
List.Free;
end;
end;
procedure TTestIdentCompletion.Test_FindCodeContext_ProcParams;
var
SrcMark: TFDMarker;
@ -134,6 +163,45 @@ begin
end;
end;
procedure TTestIdentCompletion.Test_FindCodeContext_ProcParams_Amp;
var
SrcMark: TFDMarker;
CursorPos: TCodeXYPosition;
CodeContexts: TCodeContextInfo;
begin
StartProgram;
Add([
'type &array = byte;',
'{#a}procedure &procedure(&type, j: &array);',
'begin',
'end;',
'{#b}procedure &procedure(s, &h: string);',
'begin',
'end;',
'begin',
' &procedure(3,{#c}4);',
'end.']);
ParseSimpleMarkers(Code);
SrcMark:=FindMarker('c','#');
AssertNotNull('missing src marker #c',SrcMark);
MainTool.CleanPosToCaret(SrcMark.CleanPos,CursorPos);
CodeContexts:=nil;
try
if not CodeToolBoss.FindCodeContext(Code,CursorPos.X,CursorPos.Y,CodeContexts)
then begin
WriteSource(CursorPos);
Fail('CodeToolBoss.FindCodeContext');
end;
AssertEquals('CodeContexts.Count',2,CodeContexts.Count);
//for i:=0 to CodeContexts.Count-1 do
// debugln(['TTestIdentCompletion.Test_FindCodeContext_ProcParams ',i,' ',CodeContexts[i].AsDebugString(true)]);
CheckCodeContext(CodeContexts[0],'b');
CheckCodeContext(CodeContexts[1],'a');
finally
CodeContexts.Free;
end;
end;
procedure TTestIdentCompletion.Test_FindCodeContext_ProcParams_NoClosingBracket;
var
SrcMark: TFDMarker;