mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-13 08:09:22 +02:00
SynEdit: Starting on Ifdef Markup
git-svn-id: trunk@41090 -
This commit is contained in:
parent
8ddfe52d9b
commit
f5dd5b7aa8
@ -45,11 +45,12 @@ type
|
||||
function GetPoint(const Index : Integer) : TPoint;
|
||||
function GetPointCount : Integer;
|
||||
function GetStartPoint(const Index : Integer) : TPoint;
|
||||
procedure SetCount(const AValue : Integer); override;
|
||||
function GetMatch(const Index : Integer) : TSynMarkupHighAllMatch;
|
||||
procedure SetEndPoint(const Index : Integer; const AValue : TPoint);
|
||||
procedure SetMatch(const Index : Integer; const AValue : TSynMarkupHighAllMatch);
|
||||
procedure SetStartPoint(const Index : Integer; const AValue : TPoint);
|
||||
protected
|
||||
procedure SetCount(const AValue : Integer); override;
|
||||
public
|
||||
constructor Create;
|
||||
Function MaybeReduceCapacity : Boolean;
|
||||
|
@ -23,7 +23,7 @@ unit SynEditMarkupIfDef;
|
||||
interface
|
||||
|
||||
uses
|
||||
SysUtils, types, SynEditMarkup, SynEditMiscClasses, SynHighlighterPas,
|
||||
SysUtils, types, SynEditMiscClasses, SynHighlighterPas,
|
||||
SynEditMarkupHighAll, SynEditHighlighterFoldBase, SynEditFoldedView, LazSynEditText,
|
||||
SynEditMiscProcs, LazClasses, LazLoggerBase, Graphics, LCLProc;
|
||||
|
||||
@ -81,6 +81,7 @@ type
|
||||
FNodeState, FOpeningPeerNodeState: TSynMarkupIfdefNodeStateEx;
|
||||
FNodeFlags: SynMarkupIfDefNodeFlags;
|
||||
FPeer1, FPeer2: TSynMarkupHighIfDefEntry;
|
||||
FRelativeNestDepth: Integer;
|
||||
FStartColumn, FEndColumn: Integer;
|
||||
function GetIsDisabled: Boolean;
|
||||
function GetIsEnabled: Boolean;
|
||||
@ -97,6 +98,7 @@ type
|
||||
procedure SetPeer(APeerType: TSynMarkupIfdefNodeType; ANewPeer: TSynMarkupHighIfDefEntry);
|
||||
procedure ClearPeerField(APeer: PSynMarkupHighIfDefEntry);
|
||||
procedure RemoveForwardPeers;
|
||||
procedure MaybeClearOtherPeerField(APeerField: PSynMarkupHighIfDefEntry);
|
||||
|
||||
function GetPeerField(APeerType: TSynMarkupIfdefNodeType): PSynMarkupHighIfDefEntry;
|
||||
function GetOtherPeerField(APeer: PSynMarkupHighIfDefEntry): PSynMarkupHighIfDefEntry;
|
||||
@ -125,6 +127,8 @@ type
|
||||
property Line: TSynMarkupHighIfDefLinesNode read FLine write SetLine;
|
||||
property StartColumn: Integer read FStartColumn write FStartColumn;
|
||||
property EndColumn: Integer read FEndColumn write FEndColumn;
|
||||
// RelativeNestDepth (opening depth)) First node is always 0 // nodes in line can be negative
|
||||
property RelativeNestDepth: Integer read FRelativeNestDepth;
|
||||
function ClosingPeer: TSynMarkupHighIfDefEntry;
|
||||
// COMMENT BEFORE AUTO COMPLETE !!!!!
|
||||
property IfDefPeer: TSynMarkupHighIfDefEntry index idnIfdef read GetPeer write SetPeer;
|
||||
@ -573,7 +577,7 @@ end;
|
||||
|
||||
function TSynRefCountedDict.GetMatchAtChar(AText: PChar; ATextLen: Integer): Integer;
|
||||
begin
|
||||
FDict.GetMatchAtChar(AText, ATextLen, @CheckWordEnd);
|
||||
Result := FDict.GetMatchAtChar(AText, ATextLen, @CheckWordEnd);
|
||||
end;
|
||||
|
||||
{ TSynMarkupHighIfDefEntry }
|
||||
@ -762,7 +766,7 @@ end;
|
||||
procedure TSynMarkupHighIfDefEntry.SetPeer(APeerType: TSynMarkupIfdefNodeType;
|
||||
ANewPeer: TSynMarkupHighIfDefEntry);
|
||||
var
|
||||
OwnPeerField, OwnOtherPeerField, OthersPeerField: PSynMarkupHighIfDefEntry;
|
||||
OwnPeerField, OthersPeerField: PSynMarkupHighIfDefEntry;
|
||||
begin
|
||||
//assert((ANewPeer=nil) or (APeerType = ANewPeer.NodeType), 'APeerType = ANewPeer.NodeType'); // elseif can be set as ifdef
|
||||
OwnPeerField := GetPeerField(APeerType);
|
||||
@ -772,43 +776,32 @@ begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
if OwnPeerField^ <> nil then begin
|
||||
// The PeerField in the old peer
|
||||
assert(OwnPeerField^.GetPeerField(NodeType)^ = self, 'Peer does not point back to self');
|
||||
ClearPeerField(OwnPeerField);
|
||||
end;
|
||||
ClearPeerField(OwnPeerField);
|
||||
|
||||
if ANewPeer <> nil then begin
|
||||
// If new peer is part of another pair, disolve that pair. This may set OwnPeerField = nil, if new pair points to this node
|
||||
ANewPeer.SetPeer(NodeType, nil);
|
||||
if ANewPeer = nil then begin
|
||||
OwnPeerField^ := ANewPeer;
|
||||
|
||||
if (NodeType in [idnIfdef, idnEndIf]) and (ANewPeer <> nil) then begin
|
||||
// idnIfdef, idnEndIf are only allowed either ONE peer
|
||||
OwnOtherPeerField := GetOtherPeerField(OwnPeerField);
|
||||
if OwnOtherPeerField^ <> nil then begin
|
||||
debugln(['Setting other peer to nil while setting ',dbgs(APeerType),' to ',dbgs(NodeType)]);
|
||||
OwnOtherPeerField^.SetPeer(NodeType, nil);
|
||||
assert(OwnOtherPeerField^ = nil, 'OwnOtherPeerField was emptied, by setting the peers backpointer to nil')
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
OwnPeerField^ := ANewPeer;
|
||||
|
||||
if OwnPeerField^ = nil then begin
|
||||
if not IsForwardPeerField(OwnPeerField) then
|
||||
SetOpeningPeerNodeState(idnUnknown, idnUnknown);
|
||||
end
|
||||
else begin
|
||||
OthersPeerField := OwnPeerField^.GetPeerField(NodeType);
|
||||
assert(OthersPeerField^ = nil, 'Peer is not empty');
|
||||
OthersPeerField^ := self;
|
||||
// If new peer is part of another pair, disolve that pair. This may set OwnPeerField = nil, if new pair points to this node
|
||||
assert(ANewPeer.GetPeer(NodeType) <> self, 'New peer points to this, but was not known by this / link is not bidirectional');
|
||||
if (NodeType = idnElseIf) and (APeerType = idnElse) then // APeerType never is idnElseIf;
|
||||
OthersPeerField := ANewPeer.GetPeerField(idnIfdef) // act as ifdef
|
||||
else
|
||||
OthersPeerField := ANewPeer.GetPeerField(NodeType);
|
||||
ANewPeer.ClearPeerField(OthersPeerField);
|
||||
MaybeClearOtherPeerField(OwnPeerField);
|
||||
ANewPeer.MaybeClearOtherPeerField(OthersPeerField);
|
||||
|
||||
OthersPeerField^ := Self;
|
||||
OwnPeerField^ := ANewPeer;
|
||||
|
||||
if IsForwardPeerField(OwnPeerField) then
|
||||
OwnPeerField^.SetOpeningPeerNodeState(NodeState, NodeStateForPeer(OwnPeerField^.NodeType))
|
||||
else
|
||||
SetOpeningPeerNodeState(OwnPeerField^.NodeState, OwnPeerField^.NodeStateForPeer(NodeType));
|
||||
|
||||
end;
|
||||
|
||||
end;
|
||||
@ -816,6 +809,8 @@ end;
|
||||
procedure TSynMarkupHighIfDefEntry.ClearPeerField(APeer: PSynMarkupHighIfDefEntry);
|
||||
begin
|
||||
if APeer^ = nil then exit;
|
||||
// assert(APeer^.GetPeerField(NodeType)^ = self, 'ClearPeerField: Peer does not point back to self');
|
||||
|
||||
if IsForwardPeerField(APeer) then
|
||||
APeer^.SetOpeningPeerNodeState(idnUnknown, idnUnknown)
|
||||
else
|
||||
@ -827,7 +822,7 @@ begin
|
||||
if APeer^.FPeer2 = self then
|
||||
APeer^.FPeer2 := nil
|
||||
else
|
||||
assert(false, 'ClearPeerField did not find back reference');
|
||||
assert(false, 'ClearPeerField: did not find back reference');
|
||||
APeer^ := nil;
|
||||
end;
|
||||
|
||||
@ -846,6 +841,22 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSynMarkupHighIfDefEntry.MaybeClearOtherPeerField(APeerField: PSynMarkupHighIfDefEntry);
|
||||
var
|
||||
OwnOtherPeerField: PSynMarkupHighIfDefEntry;
|
||||
begin
|
||||
if not (NodeType in [idnIfdef, idnEndIf]) then
|
||||
exit;
|
||||
|
||||
// idnIfdef, idnEndIf are only allowed either ONE peer
|
||||
OwnOtherPeerField := GetOtherPeerField(APeerField);
|
||||
if OwnOtherPeerField^ <> nil then begin
|
||||
debugln(['Setting other peer to nil while setting (p1=True / P2=false)', dbgs(APeerField=@FPeer1)]);
|
||||
ClearPeerField(OwnOtherPeerField);
|
||||
assert(OwnOtherPeerField^ = nil, 'OwnOtherPeerField was emptied, by setting the peers backpointer to nil')
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSynMarkupHighIfDefEntry.ApplyNodeStateToLine(ARemove: Boolean = False);
|
||||
var
|
||||
i: Integer;
|
||||
@ -1006,7 +1017,7 @@ end;
|
||||
|
||||
procedure TSynMarkupHighIfDefLinesNode.MakeDisposed;
|
||||
begin
|
||||
FLineFlags := [idlDisposed];
|
||||
FLineFlags := [idlDisposed] + FLineFlags * [idlInGlobalClear];
|
||||
while EntryCount > 0 do
|
||||
DeletEntry(EntryCount-1, True);
|
||||
assert((FDisabledEntryOpenCount =0) and (FDisabledEntryCloseCount = 0), 'no close count left over');
|
||||
@ -1430,55 +1441,104 @@ end;
|
||||
procedure TSynMarkupHighIfDefLinesTree.ConnectPeers(var ANode: TSynMarkupHighIfDefLinesNodeInfo;
|
||||
var ANestList: TSynMarkupHighIfDefLinesNodeInfoList; AOuterLines: TLazSynEditNestedFoldsList);
|
||||
var
|
||||
PeerList: array of TSynMarkupHighIfDefEntry;
|
||||
NestDepth, LowerNestDepth: Integer;
|
||||
PeerList: array of TSynMarkupHighIfDefEntry; // List of Else/Endif in the current line, that where opened in a previous line
|
||||
OpenList: array of TSynMarkupHighIfDefEntry; // List of IfDef/Else in the current line
|
||||
CurDepth, MaxListIdx, MinOpenDepth, MaxOpenDepth, MaxPeerDepth, MinPeerDepth: Integer;
|
||||
i, j, OtherDepth: Integer;
|
||||
OtherLine: TSynMarkupHighIfDefLinesNodeInfo;
|
||||
|
||||
function OpenIdx(AIdx: Integer): Integer; // correct negative idx
|
||||
begin
|
||||
Result := AIdx;
|
||||
if Result >= 0 then exit;
|
||||
Result := MaxListIdx + (-AIdx);
|
||||
end;
|
||||
|
||||
begin
|
||||
NestDepth := ANode.NestDepthAtNodeEnd;
|
||||
LowerNestDepth := MaxInt;
|
||||
SetLength(PeerList, NestDepth + ANode.EntryCount + 1);
|
||||
OtherLine.ClearInfo;
|
||||
for i := ANode.EntryCount - 1 downto 0 do begin
|
||||
/// Scan for onel line blocks
|
||||
CurDepth := ANode.NestDepthAtNodeStart;
|
||||
MinOpenDepth := MaxInt;
|
||||
MaxOpenDepth := -1;
|
||||
MinPeerDepth := MaxInt;
|
||||
MaxPeerDepth := -1;
|
||||
|
||||
MaxListIdx := CurDepth + ANode.EntryCount + 1;
|
||||
SetLength(OpenList, MaxListIdx + ANode.EntryCount);
|
||||
SetLength(PeerList, MaxListIdx);
|
||||
|
||||
for i := 0 to ANode.EntryCount - 1 do begin
|
||||
case ANode.Entry[i].NodeType of
|
||||
idnIfdef: begin
|
||||
if (LowerNestDepth <= NestDepth) and (PeerList[NestDepth].IfDefPeer <> ANode.Entry[i])
|
||||
then begin
|
||||
Debugln(['New Peer for ',dbgs(PeerList[NestDepth].NodeType), ' to ifdef same line']);
|
||||
PeerList[NestDepth].IfDefPeer := ANode.Entry[i]; // update closing node
|
||||
end;
|
||||
dec(NestDepth);
|
||||
inc(CurDepth);
|
||||
OpenList[OpenIdx(CurDepth)] := ANode.Entry[i]; // Store IfDef, with Index at end of IfDef (inside block)
|
||||
if CurDepth < MinOpenDepth then MinOpenDepth := CurDepth;
|
||||
if CurDepth > MaxOpenDepth then MaxOpenDepth := CurDepth;
|
||||
end;
|
||||
idnElse, idnElseIf: begin
|
||||
if (LowerNestDepth <= NestDepth)
|
||||
then begin
|
||||
if PeerList[NestDepth].NodeType = idnEndIf then begin
|
||||
if PeerList[NestDepth].ElsePeer <> ANode.Entry[i] then begin
|
||||
Debugln(['New Peer for ',dbgs(PeerList[NestDepth].NodeType), ' to else same line']);
|
||||
PeerList[NestDepth].ElsePeer := ANode.Entry[i]; // update closing node
|
||||
end;
|
||||
end
|
||||
else begin
|
||||
DebugLn('Ignoring invalid double else');
|
||||
end;
|
||||
If CurDepth <= 0 then begin
|
||||
debugln(['Ignoring node with has no opening at all in line ', ANode.StartLine]);
|
||||
end;
|
||||
PeerList[NestDepth] := ANode.Entry[i];
|
||||
if LowerNestDepth > NestDepth then
|
||||
LowerNestDepth := NestDepth;
|
||||
|
||||
if (CurDepth >= MinOpenDepth) and (CurDepth <= MaxOpenDepth) then begin
|
||||
// Opening Node on this line
|
||||
assert(CurDepth = MaxOpenDepth, 'ConnectPeers: Same line peer skips opening node(s)');
|
||||
case OpenList[OpenIdx(CurDepth)].NodeType of
|
||||
idnIfdef, idnElseIf:
|
||||
if OpenList[OpenIdx(CurDepth)].ElsePeer <> ANode.Entry[i] then begin
|
||||
Debugln(['New Peer for ',dbgs(OpenList[OpenIdx(CurDepth)].NodeType), ' to else same line']);
|
||||
OpenList[OpenIdx(CurDepth)].ElsePeer := ANode.Entry[i];
|
||||
//dec(MaxOpenDepth); // Will be set with the current entry
|
||||
end;
|
||||
idnElse: DebugLn('Ignoring invalid double else (on same line)');
|
||||
end;
|
||||
end
|
||||
else
|
||||
If CurDepth >= 0 then begin
|
||||
// Opening Node in previous line
|
||||
PeerList[CurDepth] := ANode.Entry[i];
|
||||
assert((MaxPeerDepth=-1) or ((MinPeerDepth <= MaxPeerDepth) and (CurDepth = MinPeerDepth-1)), 'ConnectPeers: skipped noeds during line scan');
|
||||
if CurDepth < MinPeerDepth then MinPeerDepth := CurDepth;
|
||||
if CurDepth > MaxPeerDepth then MaxPeerDepth := CurDepth;
|
||||
end;
|
||||
|
||||
OpenList[OpenIdx(CurDepth)] := ANode.Entry[i]; // Store IfDef, with Index at end of IfDef (inside block)
|
||||
if CurDepth < MinOpenDepth then MinOpenDepth := CurDepth;
|
||||
if CurDepth > MaxOpenDepth then MaxOpenDepth := CurDepth;
|
||||
end;
|
||||
idnEndIf: begin
|
||||
inc(NestDepth);
|
||||
PeerList[NestDepth] := ANode.Entry[i];
|
||||
if LowerNestDepth > NestDepth then
|
||||
LowerNestDepth := NestDepth;
|
||||
If CurDepth <= 0 then begin
|
||||
debugln(['Ignoring node with has no opening at all in line', ANode.StartLine]);
|
||||
dec(CurDepth);
|
||||
continue; // This node has no opening node
|
||||
end;
|
||||
|
||||
if (CurDepth >= MinOpenDepth) and (CurDepth <= MaxOpenDepth) then begin
|
||||
// Opening Node on this line
|
||||
assert(CurDepth = MaxOpenDepth, 'ConnectPeers: Same line peer skips opening node(s)');
|
||||
if OpenList[OpenIdx(CurDepth)].EndIfPeer <> ANode.Entry[i] then begin
|
||||
Debugln(['New Peer for ',dbgs(OpenList[OpenIdx(CurDepth)].NodeType), ' to endif same line']);
|
||||
OpenList[OpenIdx(CurDepth)].EndIfPeer := ANode.Entry[i];
|
||||
dec(MaxOpenDepth);
|
||||
end;
|
||||
end
|
||||
else begin
|
||||
// Opening Node in previous line
|
||||
PeerList[CurDepth] := ANode.Entry[i];
|
||||
assert((MaxPeerDepth=-1) or ((MinPeerDepth <= MaxPeerDepth) and (CurDepth = MinPeerDepth-1)), 'ConnectPeers: skipped noeds during line scan');
|
||||
if CurDepth < MinPeerDepth then MinPeerDepth := CurDepth;
|
||||
if CurDepth > MaxPeerDepth then MaxPeerDepth := CurDepth;
|
||||
end;
|
||||
|
||||
dec(CurDepth);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Find peers in previous lines.
|
||||
|
||||
|
||||
// Find peers in previous lines. MinPeerDepth <= 0 have no opening
|
||||
// Opening (IfDef) nodes will be connected when there closing node is found.
|
||||
for i := NestDepth downto LowerNestDepth do begin
|
||||
for i := MaxPeerDepth downto Max(MinPeerDepth, 1) do begin
|
||||
// Todo: MAybe optimize, if it can be known that an existing peer link is correct
|
||||
//case PeerList[i].NodeType of
|
||||
// idnElse: if PeerList[i].IfDefPeer <> nil then continue;
|
||||
@ -1507,8 +1567,20 @@ begin
|
||||
idnIfdef: begin
|
||||
assert(PeerList[i].NodeType in [idnElse, idnElseIf, idnEndIf], 'PeerList[i].NodeType in [idnElse, idnEndIf] for other ifdef');
|
||||
if PeerList[i].IfDefPeer <> OtherLine.Entry[j] then begin
|
||||
Debugln(['New Peer for ',dbgs(PeerList[i].NodeType), ' to ifdef other line']);
|
||||
PeerList[i].IfDefPeer := OtherLine.Entry[j];
|
||||
if OtherLine.Entry[j].GetPeer(PeerList[i].NodeType) <> nil then begin
|
||||
debugln(['COMPARING MaxPeerdepth for ',dbgs(PeerList[i].NodeType), ' to ifdef other line']);
|
||||
if (OtherLine.NestDepthAtNodeStart + OtherLine.Entry[j].RelativeNestDepth + 1 = i
|
||||
// ANode.NestDepthAtNodeStart + PeerList[i].RelativeNestDepth
|
||||
)
|
||||
then begin
|
||||
Debugln(['New Peer (REPLACE) for ',dbgs(PeerList[i].NodeType), ' to ifdef other line']);
|
||||
PeerList[i].IfDefPeer := OtherLine.Entry[j];
|
||||
end;
|
||||
end
|
||||
else begin
|
||||
Debugln(['New Peer for ',dbgs(PeerList[i].NodeType), ' to ifdef other line']);
|
||||
PeerList[i].IfDefPeer := OtherLine.Entry[j];
|
||||
end;
|
||||
end;
|
||||
j := -1;
|
||||
break;
|
||||
@ -1517,8 +1589,20 @@ begin
|
||||
assert(PeerList[i].NodeType in [idnElse, idnElseIf, idnEndIf], 'PeerList[i].NodeType in [idnElse, idnEndIf] for other else');
|
||||
if (PeerList[i].NodeType = idnEndIf) then begin
|
||||
if PeerList[i].ElsePeer <> OtherLine.Entry[j] then begin
|
||||
Debugln(['New Peer for ',dbgs(PeerList[i].NodeType), ' to else other line']);
|
||||
PeerList[i].ElsePeer := OtherLine.Entry[j];
|
||||
|
||||
if OtherLine.Entry[j].GetPeer(PeerList[i].NodeType) <> nil then begin
|
||||
debugln(['COMPARING MaxPeerdepth for ',dbgs(PeerList[i].NodeType), ' to else other line']);
|
||||
if OtherLine.NestDepthAtNodeStart + OtherLine.Entry[j].RelativeNestDepth = i
|
||||
// ANode.NestDepthAtNodeStart + PeerList[i].RelativeNestDepth
|
||||
then begin
|
||||
Debugln(['New Peer (REPLACE) for ',dbgs(PeerList[i].NodeType), ' to else other line']);
|
||||
PeerList[i].ElsePeer := OtherLine.Entry[j];
|
||||
end;
|
||||
end
|
||||
else begin
|
||||
Debugln(['New Peer for ',dbgs(PeerList[i].NodeType), ' to else other line']);
|
||||
PeerList[i].ElsePeer := OtherLine.Entry[j];
|
||||
end;
|
||||
end;
|
||||
j := -1;
|
||||
end
|
||||
@ -1526,8 +1610,19 @@ begin
|
||||
if (PeerList[i].NodeType in [idnElseIf, idnElse]) and (OtherLine.Entry[j].NodeType = idnElseIf)
|
||||
then begin
|
||||
if PeerList[i].IfDefPeer <> OtherLine.Entry[j] then begin
|
||||
Debugln(['New Peer for ',dbgs(PeerList[i].NodeType), ' to else other line']);
|
||||
PeerList[i].IfDefPeer := OtherLine.Entry[j];
|
||||
if OtherLine.Entry[j].GetPeer(PeerList[i].NodeType) <> nil then begin
|
||||
debugln(['COMPARING MaxPeerdepth for ',dbgs(PeerList[i].NodeType), ' to else other line']);
|
||||
if OtherLine.NestDepthAtNodeStart + OtherLine.Entry[j].RelativeNestDepth = i
|
||||
// ANode.NestDepthAtNodeStart + PeerList[i].RelativeNestDepth
|
||||
then begin
|
||||
Debugln(['New Peer (REPLACE) for ',dbgs(PeerList[i].NodeType), ' to else other line']);
|
||||
PeerList[i].IfDefPeer := OtherLine.Entry[j];
|
||||
end;
|
||||
end
|
||||
else begin
|
||||
Debugln(['New Peer for ',dbgs(PeerList[i].NodeType), ' to else other line']);
|
||||
PeerList[i].IfDefPeer := OtherLine.Entry[j];
|
||||
end;
|
||||
end;
|
||||
j := -1;
|
||||
end
|
||||
@ -1825,6 +1920,10 @@ DebugLn(['change startline ', WorkNode.StartLine ,' to ', aLinePos]);
|
||||
end;
|
||||
|
||||
assert(WorkNode.StartLine < aLinePos);
|
||||
WorkLine := WorkNode.StartLine + WorkNode.ScanEndOffs;
|
||||
if (WorkLine >= aLinePos) then
|
||||
WorkNode.ScanEndOffs := aLinePos - 1 - WorkNode.StartLine;
|
||||
|
||||
WorkLine := WorkNode.StartLine + WorkNode.LastEntryEndLineOffs;
|
||||
i := WorkNode.EntryCount - 1;
|
||||
if (WorkLine >= aLinePos) and (i >= 0) then begin
|
||||
@ -2068,7 +2167,7 @@ var
|
||||
fn, fn2: TSynFoldNodeInfo;
|
||||
LogStartX, LogEndX, LineLen, LineOffs: Integer;
|
||||
Entry: TSynMarkupHighIfDefEntry;
|
||||
i, c: Integer;
|
||||
i, c, RelNestDepth, RelNestDepthNext: Integer;
|
||||
NType: TSynMarkupIfdefNodeType;
|
||||
begin
|
||||
DebugLnEnter(['>> ScanLine ', ALine, ' ', dbgs(ANodeForLine), ' ', dbgs(ACheckOverlapOnCreateLine)]);
|
||||
@ -2081,6 +2180,7 @@ begin
|
||||
if (ANodeForLine <> nil) and (ANodeForLine.EntryCapacity < FoldNodeInfoList.Count) then
|
||||
ANodeForLine.EntryCapacity := FoldNodeInfoList.Count;
|
||||
NodesAddedCnt := 0;
|
||||
RelNestDepthNext := 0;
|
||||
|
||||
LineTextLower := LowerCase(Lines[ToIdx(ALine)]);
|
||||
LineLen := Length(LineTextLower);
|
||||
@ -2102,11 +2202,13 @@ begin
|
||||
// assert(LogStartX >= LogEndX, 'ifdef xpos found before end of previous ifdef');
|
||||
|
||||
LogEndX := FindCloseCurlyBracket(LogStartX+1, LineOffs) + 1;
|
||||
RelNestDepth := RelNestDepthNext;
|
||||
case TheDict.GetMatchAtChar(@LineTextLower[LogStartX], LineLen + 1 - LogStartX) of
|
||||
1: // ifdef
|
||||
begin
|
||||
assert(sfaOpen in fn.FoldAction, 'sfaOpen in fn.FoldAction');
|
||||
NType := idnIfdef;
|
||||
inc(RelNestDepthNext);
|
||||
end;
|
||||
2: // else
|
||||
begin
|
||||
@ -2122,6 +2224,7 @@ begin
|
||||
begin
|
||||
assert(sfaClose in fn.FoldAction, 'sfaOpen in fn.FoldAction');
|
||||
NType := idnEndIf;
|
||||
dec(RelNestDepthNext);
|
||||
end;
|
||||
4: // ElseIf
|
||||
begin
|
||||
@ -2141,6 +2244,7 @@ begin
|
||||
end;
|
||||
|
||||
Entry := GetEntry(LogStartX, LogEndX, LineOffs, NType);
|
||||
Entry.FRelativeNestDepth := RelNestDepth;
|
||||
|
||||
if LineOffs > 0 then begin
|
||||
if ANodeForLine.LastEntryEndLineOffs <> LineOffs then begin
|
||||
|
@ -46,6 +46,7 @@ type
|
||||
function TestText3: TStringArray;
|
||||
function TestText4: TStringArray;
|
||||
function TestText5: TStringArray;
|
||||
function TestText6: TStringArray;
|
||||
|
||||
procedure CheckNodes(AName: String; ALine: Integer;
|
||||
AExp: array of TNodeExpect);
|
||||
@ -422,6 +423,15 @@ begin
|
||||
AddLine('{$Endif}' );
|
||||
AddLine('' );
|
||||
AddLine('' );
|
||||
AddLine('' );
|
||||
// 20
|
||||
AddLine('{$IFDEF a}' );
|
||||
AddLine('' );
|
||||
// 1 - 9 11 - 21 22 - 29 30 - 37 38 - 46 48 - 56 58 - 68 69 - 77
|
||||
AddLine('{$EndIf} {$IFDEF a} {$ELSE} {$ELSE} {$ENDIF} {$endif} {$IFDEF a} {$ENDIF} ');
|
||||
AddLine('' );
|
||||
AddLine('' );
|
||||
AddLine('' );
|
||||
end;
|
||||
|
||||
function TTestMarkupIfDef.TestText3: TStringArray;
|
||||
@ -482,6 +492,42 @@ begin
|
||||
AddLine('' );
|
||||
end;
|
||||
|
||||
function TTestMarkupIfDef.TestText6: TStringArray;
|
||||
procedure AddLine(s: String);
|
||||
begin
|
||||
SetLength(Result, Length(Result)+1);
|
||||
Result[Length(Result)-1] := s;
|
||||
end;
|
||||
begin
|
||||
// 1
|
||||
AddLine('//' );
|
||||
AddLine('{$IFDEF a}' );
|
||||
AddLine('' );
|
||||
AddLine('' );
|
||||
// 5
|
||||
AddLine('' );
|
||||
AddLine(' {$IFDEF b}' );
|
||||
AddLine('' );
|
||||
AddLine('' );
|
||||
AddLine('' );
|
||||
// 10
|
||||
AddLine(' {$IFDEF c}' );
|
||||
AddLine('' );
|
||||
AddLine('' );
|
||||
AddLine('' );
|
||||
AddLine(' {$Endif}' );
|
||||
// 15
|
||||
AddLine('' );
|
||||
AddLine('' );
|
||||
AddLine('' );
|
||||
AddLine(' {$Endif}' );
|
||||
AddLine('' );
|
||||
// 20
|
||||
AddLine('' );
|
||||
|
||||
|
||||
end;
|
||||
|
||||
function TTestMarkupIfDef.CreateTheHighLighter: TSynCustomFoldHighlighter;
|
||||
begin
|
||||
Result := TSynPasSyn.Create(nil);
|
||||
@ -927,6 +973,15 @@ FTestTree.DebugPrint(true);DebugLn;
|
||||
CheckNodesXY('', 6, [3, 14], 0);
|
||||
|
||||
|
||||
// Insert IFDEF into empty text
|
||||
ReCreateEditForTreeTest(TestTextNoIfDef);
|
||||
FTestTree.ValidateRange(1, 5, FOpenings);
|
||||
SynEdit.TextBetweenPoints[point(1, 3),point(1, 3)] := '{$IFDEF a}';
|
||||
FTestTree.ValidateRange(1, 5, FOpenings);
|
||||
FTestTree.DebugPrint(true);DebugLn;
|
||||
CheckNodesXY('Insert IFDEF into empty text', 3, [1,11], 0);
|
||||
|
||||
|
||||
FTestTree.DiscardOpeningList(FOpenings);
|
||||
FOpenings := nil;;
|
||||
FTestTree.Free;
|
||||
@ -1128,16 +1183,9 @@ DebugLn('--------');FTestTree.DebugPrint(true);
|
||||
FTestTree.ValidateRange(1, 18, FOpenings);
|
||||
DebugLn('--------');FTestTree.DebugPrint(true);
|
||||
// ONe and only one of the 2 ends should have a peer
|
||||
nd := FTestTree.FindNodeAtPosition(33, afmNil);
|
||||
if nd.HasNode and (nd.EntryCount > 0) and (nd.Entry[0].EndIfPeer.Line.GetPosition = 4) then begin
|
||||
CheckNodes(n, 2, [ ExpN( 1,11, idnIfdef, EpEnd(4, 1)) ]);
|
||||
CheckNodes(n, 4, [ ExpN( 1, 9, idnEndIf, EpIf(2, 1)) ]);
|
||||
CheckNodes(n, 6, [ ExpN( 1, 9, idnEndIf, EpIf(-1, -1)) ]); // must not have a peer
|
||||
end else begin
|
||||
CheckNodes(n, 2, [ ExpN( 1,11, idnIfdef, EpEnd(6, 1)) ]);
|
||||
CheckNodes(n, 4, [ ExpN( 1, 9, idnEndIf, EpIf(-1, -1)) ]); // must not have a peer
|
||||
CheckNodes(n, 6, [ ExpN( 1, 9, idnEndIf, EpIf(2, 1)) ]);
|
||||
end;
|
||||
CheckNodes(n, 2, [ ExpN( 1,11, idnIfdef, EpEnd(4, 1)) ]);
|
||||
CheckNodes(n, 4, [ ExpN( 1, 9, idnEndIf, EpIf(2, 1)) ]);
|
||||
CheckNodes(n, 6, [ ExpN( 1, 9, idnEndIf, EpIf(-1, -1)) ]); // must not have a peer
|
||||
// One and only one else may be connected to if and one (but maybe the other) to endif
|
||||
CheckNodes(n,10, [ ExpN( 1,11, idnIfdef) ]); // EpElse(12, 1) // or 14
|
||||
CheckNodes(n,12, [ ExpN( 1, 8, idnElse) ]);
|
||||
@ -1354,6 +1402,78 @@ DebugLn('--------');FTestTree.DebugPrint(true);
|
||||
|
||||
|
||||
|
||||
{%region Insert If/end to create invalid peering, that must be resolved }
|
||||
n := 'Peers, TestText6: Resolve left-over binding: ' +
|
||||
'Insert Ifdef in visible part, with node inbetween';
|
||||
ReCreateEditForTreeTest(TestText6);
|
||||
FTestTree.ValidateRange(1, 20, FOpenings);
|
||||
CheckNodes(n, 2, [ ExpN( 1,11, idnIfdef ) ]);
|
||||
CheckNodes(n, 6, [ ExpN( 2,12, idnIfdef, EpEnd(18, 2)) ]);
|
||||
CheckNodes(n,10, [ ExpN( 3,13, idnIfdef, EpEnd(14, 3)) ]);
|
||||
CheckNodes(n,14, [ ExpN( 3,11, idnEndIf, EpIf(10, 3)) ]);
|
||||
CheckNodes(n,18, [ ExpN( 2,10, idnEndIf, EpIf( 6, 2)) ]);
|
||||
|
||||
SynEdit.TextBetweenPoints[point(1, 8),point(1, 8)] := ' {$IfDef X}';
|
||||
FTestTree.ValidateRange(1, 20, FOpenings);
|
||||
DebugLn('--------');FTestTree.DebugPrint(true);
|
||||
CheckNodes(n, 2, [ ExpN( 1,11, idnIfdef ) ]);
|
||||
CheckNodes(n, 6, [ ExpN( 2,12, idnIfdef ) ]);
|
||||
CheckNodes(n, 8, [ ExpN( 4,14, idnIfdef, EpEnd(18, 2)) ]);
|
||||
CheckNodes(n,10, [ ExpN( 3,13, idnIfdef, EpEnd(14, 3)) ]);
|
||||
CheckNodes(n,14, [ ExpN( 3,11, idnEndIf, EpIf(10, 3)) ]);
|
||||
CheckNodes(n,18, [ ExpN( 2,10, idnEndIf, EpIf( 8, 4)) ]);
|
||||
|
||||
n := n + ' Remove again';
|
||||
SynEdit.TextBetweenPoints[point(1, 8),point(14, 8)] := '';
|
||||
FTestTree.ValidateRange(1, 20, FOpenings);
|
||||
CheckNodes(n, 2, [ ExpN( 1,11, idnIfdef ) ]);
|
||||
CheckNodes(n, 6, [ ExpN( 2,12, idnIfdef, EpEnd(18, 2)) ]);
|
||||
CheckNodes(n,10, [ ExpN( 3,13, idnIfdef, EpEnd(14, 3)) ]);
|
||||
CheckNodes(n,14, [ ExpN( 3,11, idnEndIf, EpIf(10, 3)) ]);
|
||||
CheckNodes(n,18, [ ExpN( 2,10, idnEndIf, EpIf( 6, 2)) ]);
|
||||
{%endregion Insert If/end to create invalid peering, that must be resolved }
|
||||
|
||||
|
||||
{%region Insert If/end to create invalid peering, that must be resolved }
|
||||
n := 'Peers, TestText6: Relosve left-over binding: ' +
|
||||
'Insert Ifdef in visible part, with node inbetween AT end of outer ifdef';
|
||||
ReCreateEditForTreeTest(TestText6);
|
||||
FTestTree.ValidateRange(1, 20, FOpenings);
|
||||
|
||||
SynEdit.TextBetweenPoints[point(12, 6),point(12, 6)] := ' {$IfDef X}';
|
||||
FTestTree.ValidateRange(1, 20, FOpenings);
|
||||
DebugLn('--------');FTestTree.DebugPrint(true);
|
||||
CheckNodes(n, 2, [ ExpN( 1,11, idnIfdef ) ]);
|
||||
CheckNodes(n, 6, [ ExpN( 2,12, idnIfdef ),
|
||||
ExpN(15,25, idnIfdef, EpEnd(18, 2))
|
||||
]);
|
||||
CheckNodes(n,10, [ ExpN( 3,13, idnIfdef, EpEnd(14, 3)) ]);
|
||||
CheckNodes(n,14, [ ExpN( 3,11, idnEndIf, EpIf(10, 3)) ]);
|
||||
CheckNodes(n,18, [ ExpN( 2,10, idnEndIf, EpIf( 6, 15)) ]);
|
||||
|
||||
n := n + ' Remove again';
|
||||
SynEdit.TextBetweenPoints[point(12, 6),point(25, 6)] := '';
|
||||
FTestTree.ValidateRange(1, 20, FOpenings);
|
||||
CheckNodes(n, 2, [ ExpN( 1,11, idnIfdef ) ]);
|
||||
CheckNodes(n, 6, [ ExpN( 2,12, idnIfdef, EpEnd(18, 2)) ]);
|
||||
CheckNodes(n,10, [ ExpN( 3,13, idnIfdef, EpEnd(14, 3)) ]);
|
||||
CheckNodes(n,14, [ ExpN( 3,11, idnEndIf, EpIf(10, 3)) ]);
|
||||
CheckNodes(n,18, [ ExpN( 2,10, idnEndIf, EpIf( 6, 2)) ]);
|
||||
{%endregion Insert If/end to create invalid peering, that must be resolved }
|
||||
|
||||
|
||||
{%region }
|
||||
n := 'P';
|
||||
ReCreateEditForTreeTest(TestText2);
|
||||
FTestTree.ValidateRange(1, 24, FOpenings);
|
||||
FTestTree.ValidateRange(1, 24, FOpenings);
|
||||
|
||||
{%endregion }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{%endregion peers}
|
||||
|
||||
|
||||
@ -1430,6 +1550,7 @@ DebugLn('--------');FTestTree.DebugPrint(true);
|
||||
|
||||
FTestTree.ValidateRange(1, 6, FOpenings);
|
||||
DebugLn('--------');FTestTree.DebugPrint(true);
|
||||
AssertEquals(n + '2 requests ' , 2, FNodeStateRequests.Count);
|
||||
AssertEquals(n + 'Got reqest for 2/1' , '1', FNodeStateRequests.Values['2/1']);
|
||||
AssertEquals(n + 'Got reqest for 4/1' , '1', FNodeStateRequests.Values['4/1']);
|
||||
CheckNodes(n, 2, [ ExpN( 1,11, idnIfdef, idnEnabled), ExpN(13,21, idnEndIf, idnEnabled ) ]);
|
||||
@ -1440,12 +1561,32 @@ DebugLn('--------');FTestTree.DebugPrint(true);
|
||||
FNodeStateRequests.Clear;
|
||||
FTestTree.SetNodeState(2,1, idnNotInCode);
|
||||
DebugLn('--------');FTestTree.DebugPrint(true);
|
||||
AssertEquals(n + 'Got NO reqest for 2/1' , '', FNodeStateRequests.Values['2/1']);
|
||||
AssertEquals(n + 'Got NO reqest for 4/1' , '', FNodeStateRequests.Values['4/1']);
|
||||
AssertEquals(n + 'NO requests ' , 0, FNodeStateRequests.Count);
|
||||
//AssertEquals(n + 'Got NO reqest for 2/1' , '', FNodeStateRequests.Values['2/1']);
|
||||
//AssertEquals(n + 'Got NO reqest for 4/1' , '', FNodeStateRequests.Values['4/1']);
|
||||
CheckNodes(n, 2, [ ExpN( 1,11, idnIfdef, idnNotInCode), ExpN(13,21, idnEndIf ) ]);
|
||||
CheckNodes(n, 4, [ ExpN( 1,11, idnIfdef, idnDisabled), ExpN(13,21, idnEndIf, idnDisabled ) ]);
|
||||
|
||||
|
||||
{%region Insert IFDEF into empty text }
|
||||
FNodeStateResponses.Clear;
|
||||
FNodeStateRequests.Clear;
|
||||
ReCreateEditForTreeTest(TestTextNoIfDef);
|
||||
FTestTree.OnNodeStateRequest := @TesTNodeStateHandler;
|
||||
|
||||
FTestTree.ValidateRange(1, 5, FOpenings);
|
||||
FTestTree.DebugPrint(true);DebugLn;
|
||||
AssertEquals(n + 'NO requests ' , 0, FNodeStateRequests.Count);
|
||||
|
||||
SynEdit.TextBetweenPoints[point(1, 3),point(1, 3)] := '{$IFDEF a}';
|
||||
FTestTree.DebugPrint(true);DebugLn;
|
||||
FTestTree.ValidateRange(1, 5, FOpenings);
|
||||
FTestTree.DebugPrint(true);DebugLn;
|
||||
AssertEquals(n + 'one requests ' , 1, FNodeStateRequests.Count);
|
||||
AssertEquals(n + 'Got reqest for 3/1' , '1', FNodeStateRequests.Values['3/1']);
|
||||
CheckNodesXY('Insert IFDEF into empty text', 3, [1,11], 0);
|
||||
{%endregion Insert IFDEF into empty text }
|
||||
|
||||
|
||||
FTestTree.DiscardOpeningList(FOpenings);
|
||||
FOpenings := nil;
|
||||
|
Loading…
Reference in New Issue
Block a user