SynEdit: fixed crash / undefined behaviour due to invalid caching of highlighter node-info. Issue #0027748

git-svn-id: trunk@48532 -
This commit is contained in:
martin 2015-03-29 21:44:39 +00:00
parent 3459fff08c
commit 901196535a
2 changed files with 42 additions and 4 deletions

View File

@ -350,7 +350,8 @@ type
procedure BeforeDetachedFromRangeList(ARangeList: TSynHighlighterRangeList); virtual;
function UpdateRangeInfoAtLine(Index: Integer): Boolean; virtual; // Returns true if range changed
// code fold - only valid if hcCodeFolding in Capabilities
procedure SetCurrentLines(const AValue: TSynEditStringsBase); virtual;
procedure SetCurrentLines(const AValue: TSynEditStringsBase); virtual; // todo remove virtual
procedure DoCurrentLinesChanged; virtual;
property LineIndex: Integer read FLineIndex;
property CurrentRanges: TSynHighlighterRangeList read FCurrentRanges;
function GetDrawDivider(Index: integer): TSynDividerDrawConfigSetting; virtual;
@ -1733,6 +1734,12 @@ begin
if FCurrentLines <> nil
then FCurrentRanges := TSynHighlighterRangeList(AValue.Ranges[GetRangeIdentifier])
else FCurrentRanges := nil;
DoCurrentLinesChanged;
end;
procedure TSynCustomHighlighter.DoCurrentLinesChanged;
begin
//
end;
procedure TSynCustomHighlighter.AttachToLines(Lines: TSynEditStringsBase);

View File

@ -165,8 +165,8 @@ type
procedure ClearData;
procedure ClearFilteredList;
procedure DoFilter(MinIndex: Integer = -1);
procedure SetLine(ALine: TLineIdx);
procedure SetLineClean(ALine: TLineIdx);
procedure SetLine(ALine: TLineIdx); // Does not clear anything, if line has not changed.
procedure SetLineClean(ALine: TLineIdx); // Does not clear anything, if line has not changed.
property HighLighter: TSynCustomFoldHighlighter read FHighLighter write FHighLighter;
public
// used by HighLighters to add data
@ -301,6 +301,7 @@ type
fRanges: TSynCustomHighlighterRanges;
FRootCodeFoldBlock: TSynCustomCodeFoldBlock;
FFoldNodeInfoList: TLazSynFoldNodeInfoList;
procedure ClearFoldNodeList;
protected
// "Range"
function GetRangeClass: TSynCustomHighlighterRangeClass; virtual;
@ -379,6 +380,9 @@ type
procedure SetLine(const NewValue: String;
LineNumber:Integer // 0 based
); override;
procedure DoCurrentLinesChanged; override;
function PerformScan(StartIndex, EndIndex: Integer; ForceEndIndex: Boolean =
False): Integer; override;
public
property FoldConfig[Index: Integer]: TSynCustomFoldConfig
read GetFoldConfig write SetFoldConfig;
@ -920,6 +924,19 @@ begin
FCodeFoldRange.MinimumCodeFoldBlockLevel := FCodeFoldRange.FCodeFoldStackSize;
end;
procedure TSynCustomFoldHighlighter.DoCurrentLinesChanged;
begin
inherited DoCurrentLinesChanged;
ClearFoldNodeList;
end;
function TSynCustomFoldHighlighter.PerformScan(StartIndex, EndIndex: Integer;
ForceEndIndex: Boolean): Integer;
begin
ClearFoldNodeList;
Result := inherited PerformScan(StartIndex, EndIndex, ForceEndIndex);
end;
function TSynCustomFoldHighlighter.CurrentCodeFoldBlockLevel: integer;
begin
assert(FCodeFoldRange <> nil, 'MinimumCodeFoldBlockLevel requires FCodeFoldRange');
@ -1028,6 +1045,16 @@ begin
DefHighlightChange(self);
end;
procedure TSynCustomFoldHighlighter.ClearFoldNodeList;
begin
if FFoldNodeInfoList <> nil then begin
if (FFoldNodeInfoList.RefCount > 1) then
ReleaseRefAndNil(FFoldNodeInfoList)
else
FFoldNodeInfoList.Clear;
end;
end;
function TSynCustomFoldHighlighter.GetFoldNodeInfo(Line: TLineIdx
): TLazSynFoldNodeInfoList;
begin
@ -1038,7 +1065,11 @@ begin
FFoldNodeInfoList := CreateFoldNodeInfoList;
FFoldNodeInfoList.AddReference;
FFoldNodeInfoList.HighLighter := Self;
end;
end
else
if (CurrentRanges <> nil) and (CurrentRanges.NeedsReScanStartIndex >= 0) then
ClearFoldNodeList;
Result := FFoldNodeInfoList;
Result.SetLineClean(Line);