mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-17 17:39:20 +02:00
SynEdit: Markup-IfDef; fix crash. Issue: #0025811
git-svn-id: trunk@44345 -
This commit is contained in:
parent
3747f3f516
commit
f65306bccd
@ -1854,6 +1854,7 @@ var
|
|||||||
i, j, OtherDepth: Integer;
|
i, j, OtherDepth: Integer;
|
||||||
OtherLine: TSynMarkupHighIfDefLinesNodeInfo;
|
OtherLine: TSynMarkupHighIfDefLinesNodeInfo;
|
||||||
PeerChanged: Boolean;
|
PeerChanged: Boolean;
|
||||||
|
CurEntry: TSynMarkupHighIfDefEntry;
|
||||||
|
|
||||||
function OpenIdx(AIdx: Integer): Integer; // correct negative idx
|
function OpenIdx(AIdx: Integer): Integer; // correct negative idx
|
||||||
begin
|
begin
|
||||||
@ -1876,10 +1877,11 @@ begin
|
|||||||
SetLength(PeerList, MaxListIdx);
|
SetLength(PeerList, MaxListIdx);
|
||||||
|
|
||||||
for i := 0 to ANode.EntryCount - 1 do begin
|
for i := 0 to ANode.EntryCount - 1 do begin
|
||||||
case ANode.Entry[i].NodeType of
|
CurEntry := ANode.Entry[i];
|
||||||
|
case CurEntry.NodeType of
|
||||||
idnIfdef: begin
|
idnIfdef: begin
|
||||||
inc(CurDepth);
|
inc(CurDepth);
|
||||||
OpenList[OpenIdx(CurDepth)] := ANode.Entry[i]; // Store IfDef, with Index at end of IfDef (inside block)
|
OpenList[OpenIdx(CurDepth)] := CurEntry; // Store IfDef, with Index at end of IfDef (inside block)
|
||||||
if CurDepth < MinOpenDepth then MinOpenDepth := CurDepth;
|
if CurDepth < MinOpenDepth then MinOpenDepth := CurDepth;
|
||||||
if CurDepth > MaxOpenDepth then MaxOpenDepth := CurDepth;
|
if CurDepth > MaxOpenDepth then MaxOpenDepth := CurDepth;
|
||||||
end;
|
end;
|
||||||
@ -1893,9 +1895,9 @@ begin
|
|||||||
assert(CurDepth = MaxOpenDepth, 'ConnectPeers: Same line peer skips opening node(s)');
|
assert(CurDepth = MaxOpenDepth, 'ConnectPeers: Same line peer skips opening node(s)');
|
||||||
case OpenList[OpenIdx(CurDepth)].NodeType of
|
case OpenList[OpenIdx(CurDepth)].NodeType of
|
||||||
idnIfdef, idnElseIf:
|
idnIfdef, idnElseIf:
|
||||||
if OpenList[OpenIdx(CurDepth)].ClosingPeer <> ANode.Entry[i] then begin
|
if OpenList[OpenIdx(CurDepth)].ClosingPeer <> CurEntry then begin
|
||||||
//Debugln(['New Peer for ',dbgs(OpenList[OpenIdx(CurDepth)].NodeType), ' to else same line']);
|
//Debugln(['New Peer for ',dbgs(OpenList[OpenIdx(CurDepth)].NodeType), ' to else same line']);
|
||||||
OpenList[OpenIdx(CurDepth)].ClosingPeer := ANode.Entry[i];
|
OpenList[OpenIdx(CurDepth)].ClosingPeer := CurEntry;
|
||||||
PeerChanged := True;
|
PeerChanged := True;
|
||||||
//dec(MaxOpenDepth); // Will be set with the current entry
|
//dec(MaxOpenDepth); // Will be set with the current entry
|
||||||
end;
|
end;
|
||||||
@ -1905,13 +1907,13 @@ begin
|
|||||||
else
|
else
|
||||||
If CurDepth >= 0 then begin
|
If CurDepth >= 0 then begin
|
||||||
// Opening Node in previous line
|
// Opening Node in previous line
|
||||||
PeerList[CurDepth] := ANode.Entry[i];
|
PeerList[CurDepth] := CurEntry;
|
||||||
assert((MaxPeerDepth=-1) or ((MinPeerDepth <= MaxPeerDepth) and (CurDepth = MinPeerDepth-1)), 'ConnectPeers: skipped noeds during line scan');
|
assert((MaxPeerDepth=-1) or ((MinPeerDepth <= MaxPeerDepth) and (CurDepth = MinPeerDepth-1)), 'ConnectPeers: skipped noeds during line scan');
|
||||||
if CurDepth < MinPeerDepth then MinPeerDepth := CurDepth;
|
if CurDepth < MinPeerDepth then MinPeerDepth := CurDepth;
|
||||||
if CurDepth > MaxPeerDepth then MaxPeerDepth := CurDepth;
|
if CurDepth > MaxPeerDepth then MaxPeerDepth := CurDepth;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
OpenList[OpenIdx(CurDepth)] := ANode.Entry[i]; // Store IfDef, with Index at end of IfDef (inside block)
|
OpenList[OpenIdx(CurDepth)] := CurEntry; // Store IfDef, with Index at end of IfDef (inside block)
|
||||||
if CurDepth < MinOpenDepth then MinOpenDepth := CurDepth;
|
if CurDepth < MinOpenDepth then MinOpenDepth := CurDepth;
|
||||||
if CurDepth > MaxOpenDepth then MaxOpenDepth := CurDepth;
|
if CurDepth > MaxOpenDepth then MaxOpenDepth := CurDepth;
|
||||||
end;
|
end;
|
||||||
@ -1925,16 +1927,16 @@ begin
|
|||||||
if (CurDepth >= MinOpenDepth) and (CurDepth <= MaxOpenDepth) then begin
|
if (CurDepth >= MinOpenDepth) and (CurDepth <= MaxOpenDepth) then begin
|
||||||
// Opening Node on this line
|
// Opening Node on this line
|
||||||
assert(CurDepth = MaxOpenDepth, 'ConnectPeers: Same line peer skips opening node(s)');
|
assert(CurDepth = MaxOpenDepth, 'ConnectPeers: Same line peer skips opening node(s)');
|
||||||
if OpenList[OpenIdx(CurDepth)].ClosingPeer <> ANode.Entry[i] then begin
|
if OpenList[OpenIdx(CurDepth)].ClosingPeer <> CurEntry then begin
|
||||||
//Debugln(['New Peer for ',dbgs(OpenList[OpenIdx(CurDepth)].NodeType), ' to endif same line']);
|
//Debugln(['New Peer for ',dbgs(OpenList[OpenIdx(CurDepth)].NodeType), ' to endif same line']);
|
||||||
OpenList[OpenIdx(CurDepth)].ClosingPeer := ANode.Entry[i];
|
OpenList[OpenIdx(CurDepth)].ClosingPeer := CurEntry;
|
||||||
PeerChanged := True;
|
PeerChanged := True;
|
||||||
end;
|
end;
|
||||||
dec(MaxOpenDepth);
|
dec(MaxOpenDepth);
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
// Opening Node in previous line
|
// Opening Node in previous line
|
||||||
PeerList[CurDepth] := ANode.Entry[i];
|
PeerList[CurDepth] := CurEntry;
|
||||||
assert((MaxPeerDepth=-1) or ((MinPeerDepth <= MaxPeerDepth) and (CurDepth = MinPeerDepth-1)), 'ConnectPeers: skipped noeds during line scan');
|
assert((MaxPeerDepth=-1) or ((MinPeerDepth <= MaxPeerDepth) and (CurDepth = MinPeerDepth-1)), 'ConnectPeers: skipped noeds during line scan');
|
||||||
if CurDepth < MinPeerDepth then MinPeerDepth := CurDepth;
|
if CurDepth < MinPeerDepth then MinPeerDepth := CurDepth;
|
||||||
if CurDepth > MaxPeerDepth then MaxPeerDepth := CurDepth;
|
if CurDepth > MaxPeerDepth then MaxPeerDepth := CurDepth;
|
||||||
@ -1957,11 +1959,12 @@ begin
|
|||||||
//end;
|
//end;
|
||||||
|
|
||||||
assert(not (PeerList[i].NodeType in [idnIfdef, idnCommentedNode]), 'multi-line peer valid');
|
assert(not (PeerList[i].NodeType in [idnIfdef, idnCommentedNode]), 'multi-line peer valid');
|
||||||
//if (PeerList[i].NodeType = idnElse) and (AOuterLines <> nil) then begin
|
|
||||||
|
// AOuterLines is only set while scanning opening lines in front of the 1st visible screenline
|
||||||
|
// (at the start of ValidateRange)
|
||||||
if (AOuterLines <> nil) then begin
|
if (AOuterLines <> nil) then begin
|
||||||
|
if PeerList[i].NodeType in [idnElse, idnElseIf] then begin
|
||||||
// todo: find multiply elseif
|
// todo: find multiply elseif
|
||||||
assert((PeerList[i].NodeType in [idnElse, idnElseIf]), 'multi-line (opening) peer valid');
|
|
||||||
// scanning outer lines
|
|
||||||
j := ToPos(AOuterLines.NodeLineEx[i-1, 1]);
|
j := ToPos(AOuterLines.NodeLineEx[i-1, 1]);
|
||||||
if j < 0 then begin
|
if j < 0 then begin
|
||||||
//debugln(['Skipping peer for ELSE with NO IFDEF at depth ', i-1, ' before line ', ANode.StartLine]);
|
//debugln(['Skipping peer for ELSE with NO IFDEF at depth ', i-1, ' before line ', ANode.StartLine]);
|
||||||
@ -1970,6 +1973,9 @@ begin
|
|||||||
OtherLine := GetOrInsertNodeAtLine(j);
|
OtherLine := GetOrInsertNodeAtLine(j);
|
||||||
MaybeValidateNode(OtherLine);
|
MaybeValidateNode(OtherLine);
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
continue; // while scanning outerlines, any EndIf can be ignored
|
||||||
|
end
|
||||||
else
|
else
|
||||||
OtherLine := ANestList.Node[i]; // Todo: keep if same al last loop, and continue at OtherDepth / j
|
OtherLine := ANestList.Node[i]; // Todo: keep if same al last loop, and continue at OtherDepth / j
|
||||||
|
|
||||||
|
@ -58,6 +58,8 @@ type
|
|||||||
function TestText9: TStringArray;
|
function TestText9: TStringArray;
|
||||||
function TestText10: TStringArray;
|
function TestText10: TStringArray;
|
||||||
function TestText11: TStringArray;
|
function TestText11: TStringArray;
|
||||||
|
function TestText11a: TStringArray;
|
||||||
|
function TestText12: TStringArray;
|
||||||
|
|
||||||
procedure CheckOpenCloseCount(AName: String; ALine: Integer;
|
procedure CheckOpenCloseCount(AName: String; ALine: Integer;
|
||||||
AExpOpenCnt, AExpCloseCnt: Integer);
|
AExpOpenCnt, AExpCloseCnt: Integer);
|
||||||
@ -705,6 +707,83 @@ begin
|
|||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TTestMarkupIfDef.TestText11a: TStringArray;
|
||||||
|
procedure AddLine(s: String);
|
||||||
|
begin
|
||||||
|
SetLength(Result, Length(Result)+1);
|
||||||
|
Result[Length(Result)-1] := s;
|
||||||
|
end;
|
||||||
|
begin
|
||||||
|
// 1
|
||||||
|
AddLine('{$if defined(cpu86)}' ); // level 0
|
||||||
|
AddLine(' {$if defined(cpu86)} '); // level 1
|
||||||
|
AddLine(' // a');
|
||||||
|
AddLine(' {$elseif defined(cpupowerpc)} '); // level 1
|
||||||
|
//5
|
||||||
|
AddLine(' // disabled ');
|
||||||
|
AddLine(' {$elseif defined(cpupowerpc)} '); // level 1
|
||||||
|
AddLine(' // enabled (invalid) ');
|
||||||
|
AddLine(' {$elseif defined(cpuarm)} '); // level 1
|
||||||
|
AddLine(' {$if defined(cpu86)}// enabled (invalid) ');
|
||||||
|
// 10
|
||||||
|
AddLine(' {$ifend}{$if defined(cpu86)}' ); // level 2
|
||||||
|
AddLine(' {$ifend}{$elseif defined(CPUX86_64)} '); // level 1 (close lvl 2)
|
||||||
|
AddLine(' // enabled (invalid) ');
|
||||||
|
AddLine(' {$if defined(cpu86)}' ); // level 2
|
||||||
|
AddLine(' {$ifend}{$if defined(cpu86)}' ); // level 2 <> 2
|
||||||
|
// 15
|
||||||
|
AddLine(' // nested ');
|
||||||
|
AddLine(' {$elseif defined(cpuarm)} '); // level 2
|
||||||
|
AddLine(' // nested ');
|
||||||
|
AddLine(' {$else} '); // level 2
|
||||||
|
AddLine(' // nested ');
|
||||||
|
// 20
|
||||||
|
AddLine(' {$ifend} '); // level 2
|
||||||
|
AddLine(' {$else} '); // level 1
|
||||||
|
AddLine(' // enabled (invalid) ');
|
||||||
|
AddLine(' {$if defined(cpu86)}' );
|
||||||
|
AddLine(' // nested ');
|
||||||
|
// 25
|
||||||
|
AddLine(' {$ifend}{$if defined(cpu86)}' );
|
||||||
|
AddLine(' // nested ');
|
||||||
|
AddLine(' {$elseif defined(cpuarm)} ');
|
||||||
|
AddLine(' // nested ');
|
||||||
|
AddLine(' {$else} ');
|
||||||
|
// 30
|
||||||
|
AddLine(' // nested ');
|
||||||
|
AddLine(' {$ifend} ');
|
||||||
|
AddLine(' {$ifend} ');
|
||||||
|
AddLine('' );
|
||||||
|
AddLine(' {$ifend} ');
|
||||||
|
// 35
|
||||||
|
AddLine('' );
|
||||||
|
AddLine('' );
|
||||||
|
AddLine('' );
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TTestMarkupIfDef.TestText12: TStringArray;
|
||||||
|
procedure AddLine(s: String);
|
||||||
|
begin
|
||||||
|
SetLength(Result, Length(Result)+1);
|
||||||
|
Result[Length(Result)-1] := s;
|
||||||
|
end;
|
||||||
|
begin
|
||||||
|
// 1
|
||||||
|
AddLine('program project1;');
|
||||||
|
AddLine('');
|
||||||
|
AddLine('{$mode objfpc}{$H+}');
|
||||||
|
AddLine('');
|
||||||
|
// 5
|
||||||
|
AddLine('uses {$IFDEF UNIX} {$IFDEF UseCThreads}');
|
||||||
|
AddLine(' cthreads, {$ENDIF} {$ENDIF} {$ifdef LCLWinCE}');
|
||||||
|
AddLine(' WinCEInt, {$endif}');
|
||||||
|
AddLine(' Interfaces, // this includes the LCL widgetset');
|
||||||
|
AddLine(' Windows,');
|
||||||
|
AddLine(' SysUtils,');
|
||||||
|
AddLine(' Forms;');
|
||||||
|
AddLine('');
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestMarkupIfDef.CheckOpenCloseCount(AName: String; ALine: Integer; AExpOpenCnt,
|
procedure TTestMarkupIfDef.CheckOpenCloseCount(AName: String; ALine: Integer; AExpOpenCnt,
|
||||||
AExpCloseCnt: Integer);
|
AExpCloseCnt: Integer);
|
||||||
var
|
var
|
||||||
@ -2030,6 +2109,62 @@ procedure TTestMarkupIfDef.TestIfDefTreePeerConnect;
|
|||||||
|
|
||||||
{%endregion }
|
{%endregion }
|
||||||
|
|
||||||
|
{%region }
|
||||||
|
for i := 1 to 34 do begin
|
||||||
|
n := 'TestText11a elseif ' + IntToStr(i);
|
||||||
|
ReCreateEditForTreeTest(TestText11a);
|
||||||
|
FTestTree.ValidateRange(i, 35, FOpenings);
|
||||||
|
|
||||||
|
n := 'TestText11a elseif ' + IntToStr(i);
|
||||||
|
ReCreateEditForTreeTest(TestText11a);
|
||||||
|
FTestTree.ValidateRange(i, i+1, FOpenings);
|
||||||
|
|
||||||
|
n := 'TestText11a elseif ' + IntToStr(i);
|
||||||
|
ReCreateEditForTreeTest(TestText11a);
|
||||||
|
FTestTree.ValidateRange(i, i+2, FOpenings);
|
||||||
|
end;
|
||||||
|
|
||||||
|
n := 'TestText11a elseif 12-30';
|
||||||
|
ReCreateEditForTreeTest(TestText11a);
|
||||||
|
FTestTree.ValidateRange(11, 30, FOpenings);
|
||||||
|
CheckNodes(n, 1, [ ExpN( 1,21, idnIfdef)]);
|
||||||
|
//CheckNodes(n, 2, [ ExpN( 1,21, idnIfdef)]);
|
||||||
|
CheckNodes(n, 11, [ ExpN( 3,11, idnEndIf, EpIf(10,13), EpNil),
|
||||||
|
ExpN(11,39, idnElseIf, EpElseIf(8, 3), EpElse(21,3)) ]);
|
||||||
|
{%endregion }
|
||||||
|
|
||||||
|
{%region issue 0025811 }
|
||||||
|
|
||||||
|
n := 'issue 0025811';
|
||||||
|
ReCreateEditForTreeTest(TestText12);
|
||||||
|
FTestTree.ValidateRange( 7, 10, FOpenings);
|
||||||
|
CheckNodes(n, 6, [ ExpN( 13,21, idnSkipTest), ExpN(22,30, idnSkipTest),
|
||||||
|
ExpN(31, 48, idnIfdef, EpNil, EpEnd(7, 13)) ]);
|
||||||
|
CheckNodes(n, 7, [ ExpN( 13,21, idnEndIf, EpIf(6, 31), EpNil) ]);
|
||||||
|
|
||||||
|
ReCreateEditForTreeTest(TestText12);
|
||||||
|
FTestTree.ValidateRange( 5, 10, FOpenings);
|
||||||
|
CheckNodes(n, 5, [ ExpN( 6,19, idnIfdef, EpNil, EpEnd(6,22)),
|
||||||
|
ExpN(20,40, idnIfdef, EpNil, EpEnd(6,13)) ]);
|
||||||
|
CheckNodes(n, 6, [ ExpN(13,21, idnEndIf, EpIf(5,20), EpNil),
|
||||||
|
ExpN(22,30, idnEndIf, EpIf(5, 6), EpNil),
|
||||||
|
ExpN(31, 48, idnIfdef, EpNil, EpEnd(7, 13)) ]);
|
||||||
|
CheckNodes(n, 7, [ ExpN( 13,21, idnEndIf, EpIf(6, 31), EpNil) ]);
|
||||||
|
|
||||||
|
ReCreateEditForTreeTest(TestText12);
|
||||||
|
FTestTree.ValidateRange( 6, 10, FOpenings);
|
||||||
|
CheckNodes(n, 5, [ ExpN( 6,19, idnIfdef, EpNil, EpEnd(6,22)),
|
||||||
|
ExpN(20,40, idnIfdef, EpNil, EpEnd(6,13)) ]);
|
||||||
|
CheckNodes(n, 6, [ ExpN(13,21, idnEndIf, EpIf(5,20), EpNil),
|
||||||
|
ExpN(22,30, idnEndIf, EpIf(5, 6), EpNil),
|
||||||
|
ExpN(31, 48, idnIfdef, EpNil, EpEnd(7, 13)) ]);
|
||||||
|
CheckNodes(n, 7, [ ExpN( 13,21, idnEndIf, EpIf(6, 31), EpNil) ]);
|
||||||
|
|
||||||
|
ReCreateEditForTreeTest(TestText12);
|
||||||
|
FTestTree.ValidateRange( 8, 10, FOpenings);
|
||||||
|
|
||||||
|
{%endregion }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FTestTree.DiscardOpeningList(FOpenings);
|
FTestTree.DiscardOpeningList(FOpenings);
|
||||||
@ -2059,7 +2194,7 @@ begin
|
|||||||
else
|
else
|
||||||
Result := TSynMarkupIfdefNodeState(StrToIntDef(v, 0));
|
Result := TSynMarkupIfdefNodeState(StrToIntDef(v, 0));
|
||||||
|
|
||||||
DebugLn('# TesTNodeStateHandler ', n, ' # ', v, ' ', dbgs(Result));
|
//DebugLn('# TesTNodeStateHandler ', n, ' # ', v, ' ', dbgs(Result));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTestMarkupIfDef.TestIfDefTreeNodeState;
|
procedure TTestMarkupIfDef.TestIfDefTreeNodeState;
|
||||||
@ -2292,7 +2427,6 @@ DebugLn('----- disabled');FTestTree.DebugPrint(true);DebugLn('-----');
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FTestTree.DiscardOpeningList(FOpenings);
|
FTestTree.DiscardOpeningList(FOpenings);
|
||||||
FOpenings := nil;
|
FOpenings := nil;
|
||||||
FTestTree.Free;
|
FTestTree.Free;
|
||||||
|
Loading…
Reference in New Issue
Block a user