diff --git a/components/synedit/syneditmarkupifdef.pp b/components/synedit/syneditmarkupifdef.pp index 12fba23365..a28260ebeb 100644 --- a/components/synedit/syneditmarkupifdef.pp +++ b/components/synedit/syneditmarkupifdef.pp @@ -98,6 +98,7 @@ type function NodeStateForPeer(APeerType: TSynMarkupIfdefNodeType): TSynMarkupIfdefNodeStateEx; procedure SetOpeningPeerNodeState(AValueOfPeer, AValueForNode: TSynMarkupIfdefNodeStateEx); + procedure SetNodeState(AValue: TSynMarkupIfdefNodeStateEx; ASkipLineState: Boolean); procedure SetNodeState(AValue: TSynMarkupIfdefNodeStateEx); function GetPeer(APeerType: TSynMarkupIfdefPeerType): TSynMarkupHighIfDefEntry; @@ -363,8 +364,8 @@ type CurrentState: TSynMarkupIfdefNodeStateEx): TSynMarkupIfdefNodeState; Procedure ValidateMatches; - procedure DoTreeUnlocked(Sender: TObject); procedure DoTreeUnlocking(Sender: TObject); + procedure DoTreeUnlocked(Sender: TObject); procedure DoTreeChanged(Sender: TObject); protected procedure DoFoldChanged(aLine: Integer); @@ -638,6 +639,11 @@ procedure TSynMarkupHighIfDefEntry.SetLine(AValue: TSynMarkupHighIfDefLinesNode) begin if FLine = AValue then Exit; + if (FNodeState = idnNotInCode) and (FLine <> nil) and + (idlNotInCodeToUnknown in FLine.LineFlags) + then + SetNodeState(idnUnknown); + RemoveNodeStateFromLine; FLine := AValue; ApplyNodeStateToLine; @@ -646,25 +652,35 @@ end; procedure TSynMarkupHighIfDefEntry.SetOpeningPeerNodeState(AValueOfPeer, AValueForNode: TSynMarkupIfdefNodeStateEx); begin + RemoveNodeStateFromLine; FOpeningPeerNodeState := AValueOfPeer; if NodeType in [idnElse, idnEndIf] then - SetNodeState(AValueForNode) + SetNodeState(AValueForNode, True) else if NodeType = idnElseIf then case AValueForNode of - idnEnabled: MakeUnknown; // Maybe keep? - idnDisabled: SetNodeState(idnDisabled); - else SetNodeState(idnUnknown); + idnEnabled: SetNodeState(idnUnknown, True); // Maybe keep? + idnDisabled: SetNodeState(idnDisabled, True); + else SetNodeState(idnUnknown, True); end; + ApplyNodeStateToLine; end; procedure TSynMarkupHighIfDefEntry.SetNodeState(AValue: TSynMarkupIfdefNodeStateEx); begin - RemoveNodeStateFromLine; - FNodeState := AValue; - ApplyNodeStateToLine; + SetNodeState(AValue, False); +end; - if AValue = idnEnabled then +procedure TSynMarkupHighIfDefEntry.SetNodeState(AValue: TSynMarkupIfdefNodeStateEx; + ASkipLineState: Boolean); +begin + if not ASkipLineState then + RemoveNodeStateFromLine; + FNodeState := AValue; + if not ASkipLineState then + ApplyNodeStateToLine; + + if FNodeState = idnEnabled then Line.FLineFlags := Line.FLineFlags + [idlNotInCodeToUnknownReq, idlNotInCodeToUnknown]; case NodeType of @@ -2475,6 +2491,7 @@ if (e<> nil) and not(e.NodeType in [idnIfdef, idnElseIf]) then DebugLn([ 'SetNod IncChangeStep; if FLockTreeCount = 0 then FNotifyLists[itnChanged].CallNotifyEvents(Self); + //DebugLn([ 'SetNodeState ', ALinePos, '/', 'AstartPos', AstartPos, ' ', dbgs(AState)]); end; e.NodeState := AState; @@ -2957,7 +2974,7 @@ begin else Result := idnInvalid; - DebugLn(['STATE REQUEST ', LinePos, ' ', XStartPos, ' : ', dbgs(Result)]); + //DebugLn(['STATE REQUEST ', LinePos, ' ', XStartPos, ' : ', dbgs(Result)]); end; procedure TSynEditMarkupIfDef.SetLines(const AValue: TSynEditStrings); diff --git a/components/synedit/test/testmarkupifdef.pas b/components/synedit/test/testmarkupifdef.pas index ce5b5a32bf..4590de2b23 100644 --- a/components/synedit/test/testmarkupifdef.pas +++ b/components/synedit/test/testmarkupifdef.pas @@ -53,7 +53,10 @@ type function TestText5: TStringArray; function TestText6: TStringArray; function TestText7: TStringArray; + function TestText8: TStringArray; + procedure CheckOpenCloseCount(AName: String; ALine: Integer; + AExpOpenCnt, AExpCloseCnt: Integer); procedure CheckNodes(AName: String; ALine: Integer; AExp: array of TNodeExpect); procedure CheckNodesXY(AName: String; ALine: Integer; @@ -595,6 +598,38 @@ begin end; +function TTestMarkupIfDef.TestText8: TStringArray; + procedure AddLine(s: String); + begin + SetLength(Result, Length(Result)+1); + Result[Length(Result)-1] := s; + end; +begin + // 1 + AddLine('//' ); + AddLine('{$IFDEF A} {$IFDEF B} {$ENDIF} {$ENDIF}'); + AddLine(' {$IFDEF XX}' ); + AddLine('' ); + // 5 + AddLine('{$ENDIF}'); + AddLine('' ); + AddLine('' ); + AddLine('' ); +end; + +procedure TTestMarkupIfDef.CheckOpenCloseCount(AName: String; ALine: Integer; AExpOpenCnt, + AExpCloseCnt: Integer); +var + LineNode: TSynMarkupHighIfDefLinesNodeInfo; +begin + AName := Format('%s - %s L=%d', [BaseTestName, AName, ALine]); + LineNode := FTestTree.FindNodeAtPosition(ALine, afmNil); + AssertTrue(AName + 'HasNode', LineNode.HasNode); + AssertEquals(AName + ' DisabledEntryOpenCount', AExpOpenCnt, LineNode.Node.DisabledEntryOpenCount); + AssertEquals(AName + ' DisabledEntryCloseCount', AExpCloseCnt, LineNode.Node.DisabledEntryCloseCount); + +end; + function TTestMarkupIfDef.CreateTheHighLighter: TSynCustomFoldHighlighter; begin Result := TSynPasSyn.Create(nil); @@ -1043,7 +1078,6 @@ FTestTree.DebugPrint(true); - // Insert IFDEF into empty text ReCreateEditForTreeTest(TestTextNoIfDef); FTestTree.ValidateRange(1, 5, FOpenings); @@ -1915,7 +1949,6 @@ begin ClearData; SynEdit.TextBetweenPoints[point(1, 1),point(1, 1)] := '(*'; FTestTree.ValidateRange(1, 10, FOpenings); -FTestTree.DebugPrint(true);DebugLn; CheckReq(n, []); CheckNodes(n, 2, [ ExpN( 1,12, idnCommentedIfdef, idnDisabled) ]); CheckNodes(n, 3, []); @@ -1925,7 +1958,6 @@ FTestTree.DebugPrint(true);DebugLn; ClearData; SynEdit.TextBetweenPoints[point(2, 12),point(2, 12)] := '//'; FTestTree.ValidateRange(1, 10, FOpenings); -FTestTree.DebugPrint(true);DebugLn; CheckReq(n, []); CheckNodes(n, 2, [ ExpN( 1,12, idnCommentedIfdef, idnDisabled) ]); CheckNodes(n, 3, []); @@ -1935,7 +1967,6 @@ FTestTree.DebugPrint(true);DebugLn; ClearData; SynEdit.TextBetweenPoints[point(1, 1),point(3, 1)] := ''; FTestTree.ValidateRange(1, 10, FOpenings); -FTestTree.DebugPrint(true);DebugLn; CheckReq(n, []); CheckNodes(n, 2, [ ExpN( 1,12, idnIfdef, idnDisabled) ]); CheckNodes(n, 3, [ ExpN( 1, 8, idnElse, idnEnabled) ]); @@ -1974,12 +2005,53 @@ FTestTree.DebugPrint(true);DebugLn; SynEdit.TextBetweenPoints[point(1, 3),point(1, 3)] := '{$IFDEF a}'; FTestTree.ValidateRange(1, 5, FOpenings); -FTestTree.DebugPrint(true);DebugLn; +//FTestTree.DebugPrint(true);DebugLn; CheckReq(n, [ 3, 1, 1 ]); CheckNodesXY('Insert IFDEF into empty text', 3, [1,11], 0); {%endregion Insert IFDEF into empty text } + {%region } + n := ''; + ReCreateEditForTreeTest(TestText8); + FTestTree.SetNodeState( 2, 1,idnDisabled); + FTestTree.SetNodeState( 2,12,idnInvalid); + FTestTree.SetNodeState( 3, 2,idnEnabled); +FTestTree.DebugPrint(true);DebugLn('-----'); + + FTestTree.ValidateRange( 1, 11, FOpenings); +FTestTree.DebugPrint(true);DebugLn('-----'); + CheckNodes(n, 2, [ ExpN( 1,11, idnIfdef, idnDisabled, EpNil, EpEnd(2, 35)), + ExpN(12,22, idnIfdef, idnInvalid, EpNil, EpEnd(2, 26)), + ExpN(26,34, idnEndIf, idnUnknown, EpIf(2,12), EpNil), + ExpN(35,43, idnEndIf, idnDisabled, EpIf(2, 1), EpNil) + ]); + CheckOpenCloseCount(n, 2, 1, 1); + CheckNodes(n, 3, [ ExpN( 2,13, idnIfdef, idnEnabled, EpNil, EpEnd( 5, 1)) ]); + CheckOpenCloseCount(n, 3, 0, 0); + CheckNodes(n, 5, [ ExpN( 1, 9, idnEndIf, idnEnabled, EpIf( 3, 2)) ]); + CheckOpenCloseCount(n, 5, 0, 0); + + + SynEdit.TextBetweenPoints[point(10,2),point(10,2)] := LineEnding; +FTestTree.DebugPrint(true);DebugLn('-----'); + CheckNodes(n, 2, [ ExpN( 1, 2, 1, idnIfdef, idnUnknown, EpNil, EpEnd(3, 26)) ]); + CheckNodes(n, 3, [ ExpN( 3,13, idnIfdef, idnInvalid, EpNil, EpEnd(3, 17)), + ExpN(17,25, idnEndIf, idnUnknown, EpIf(3, 3), EpNil), + ExpN(26,34, idnEndIf, idnUnknown, EpIf(2, 1), EpNil) + ]); + CheckOpenCloseCount(n, 2, 0, 0); + CheckOpenCloseCount(n, 3, 0, 0); + + + SynEdit.TextBetweenPoints[point(14,2),point(1, 3)] := ''; + + {%endregion } + + + + + FTestTree.DiscardOpeningList(FOpenings); FOpenings := nil; FTestTree.Free;