SynEdit: fix PasHighLighter for "default" modifier after property. (fix false matches). Issue #39726

(cherry picked from commit db98b76076)
This commit is contained in:
Martin 2022-05-01 18:31:37 +02:00
parent d260928002
commit a8d568ef55
3 changed files with 126 additions and 8 deletions

View File

@ -1346,8 +1346,12 @@ begin
begin
if (fRange * [rsProperty, rsAtPropertyOrReadWrite, rsAfterEqualOrColon] = [rsProperty]) and
(PasCodeFoldRange.BracketNestLevel = 0)
then
Result := tkKey else Result := tkIdentifier;
then begin
Result := tkKey;
fRange := fRange + [rsAtPropertyOrReadWrite];
end
else
Result := tkIdentifier;
end
else
if KeyComp('Out') then Result := tkKey else Result := tkIdentifier;
@ -1492,8 +1496,18 @@ end;
function TSynPasSyn.Func69: TtkTokenKind;
begin
if KeyComp('Default') then begin
if (TopPascalCodeFoldBlockType in [cfbtClass, cfbtClassSection, cfbtRecord]) then
Result := tkKey
if (PasCodeFoldRange.BracketNestLevel = 0) and
(fRange * [rsAtPropertyOrReadWrite, rsAfterEqualOrColon, rsInProcHeader] = []) and
( ( (TopPascalCodeFoldBlockType in [cfbtClass, cfbtClassSection, cfbtRecord]) and
(rsAfterClassMembers in fRange)
) or
(rsProperty in fRange)
)
then begin
Result := tkKey;
if rsProperty in fRange then
fRange := fRange + [rsAtPropertyOrReadWrite];
end
else
Result := tkIdentifier;
end else
@ -2842,7 +2856,9 @@ begin
fTokenID := tkSymbol;
inc(Run);
if fLine[Run] = '=' then
inc(Run)
inc(Run);
if rsProperty in fRange then
fRange := fRange + [rsAtPropertyOrReadWrite];
end;
procedure TSynPasSyn.CRProc;
@ -2909,6 +2925,8 @@ begin
fTokenID := tkSymbol;
inc(Run);
if fLine[Run] in ['=', '>'] then inc(Run);
if rsProperty in fRange then
fRange := fRange + [rsAtPropertyOrReadWrite];
end;
procedure TSynPasSyn.CaretProc;
@ -2974,7 +2992,11 @@ procedure TSynPasSyn.PointProc;
begin
fTokenID := tkSymbol;
inc(Run);
if fLine[Run] in ['.', ')'] then inc(Run);
if fLine[Run] in ['.', ')'] then
inc(Run)
else
if fRange * [rsProperty, rsAfterClassMembers] <> [] then // Also happens for result-type of functions (if they have a dot)
fRange := fRange + [rsAtPropertyOrReadWrite];
end;
procedure TSynPasSyn.AnsiProc;
@ -3079,6 +3101,8 @@ begin
not(rsAfterClassMembers in fRange)
then
fRange := fRange + [rsVarTypeInSpecification];
if rsProperty in fRange then
fRange := fRange + [rsAtPropertyOrReadWrite];
end;
procedure TSynPasSyn.SemicolonProc;
@ -3136,6 +3160,8 @@ begin
end else begin
Inc(Run);
fTokenID := tkSymbol;
if rsProperty in fRange then
fRange := fRange + [rsAtPropertyOrReadWrite];
end;
end;
@ -3191,6 +3217,8 @@ procedure TSynPasSyn.SymbolProc;
begin
inc(Run);
fTokenID := tkSymbol;
if rsProperty in fRange then
fRange := fRange + [rsAtPropertyOrReadWrite];
end;
function TSynPasSyn.TypeHelpersIsStored: Boolean;

View File

@ -213,9 +213,9 @@ begin
e := ExpTokens[c];
//DebugLn([FTheHighLighter.GetToken,' (',FTheHighLighter.GetTokenKind ,') at ', FTheHighLighter.GetTokenPos]);
if etiKind in e.Flags then
AssertEquals(Name + ' Kind @ TokenId Line='+IntToStr(LineIdx)+' pos='+IntToStr(c), e.ExpKind, FTheHighLighter.GetTokenKind);
AssertEquals(Name + ' Kind @ TokenId Line='+IntToStr(LineIdx)+' pos='+IntToStr(c)+'Src='+FTheHighLighter.GetToken+' @'+IntToStr(FTheHighLighter.GetTokenPos), e.ExpKind, FTheHighLighter.GetTokenKind);
if etiAttr in e.Flags then
AssertEquals(Name + ' Attr @ TokenId Line='+IntToStr(LineIdx)+' pos='+IntToStr(c), AttrVal(e.ExpAttr), AttrVal(FTheHighLighter.GetTokenAttribute));
AssertEquals(Name + ' Attr @ TokenId Line='+IntToStr(LineIdx)+' pos='+IntToStr(c)+'Src='+FTheHighLighter.GetToken+' @'+IntToStr(FTheHighLighter.GetTokenPos), AttrVal(e.ExpAttr), AttrVal(FTheHighLighter.GetTokenAttribute));
FTheHighLighter.Next;
inc(c);

View File

@ -68,6 +68,14 @@ type
implementation
const
TK_Comma = tkSymbol;
TK_Semi = tkSymbol;
TK_Dot = tkSymbol;
TK_Colon = tkSymbol;
TK_Equal = tkSymbol;
TK_Bracket = tkSymbol;
operator := (a: TtkTokenKind) : TExpTokenInfo;
begin
result := default(TExpTokenInfo);
@ -660,6 +668,88 @@ begin
tkSymbol
]);
{%endregion}
{%region property and default}
ReCreateEdit;
SetLines
([ 'Unit A; interface',
'type TFoo = class',
'default,default:default;',
'private type',
'default=integer;',
'private',
'a: default;',
'default:default.default;',
{8} 'function default(default:default):default;',
{9} 'function default(default:default.default):default.default;',
{10} 'property default[default:default]:default read default write default; default;',
{11} 'property default:default read default default default;',
{12} 'property default:default index default read default default default-default+default;',
// property could read a field inside an embedded record
{13} 'property default:default.default index {C} default.default read {C} default.default {C} default default.default * default.default;',
''
]);
CheckTokensForLine('FIELD: default,default:default;', 2,
[ tkIdentifier, TK_Comma, tkIdentifier, // default , default
TK_Colon, tkIdentifier, TK_Semi // : default;
]);
CheckTokensForLine('TYPE: default=integer;', 4,
[ tkIdentifier, TK_Equal, tkIdentifier, TK_Semi // default = integer ;
]);
CheckTokensForLine('FIELD: default:default.default;', 7,
[ tkIdentifier, TK_Colon, tkIdentifier, TK_Dot, tkIdentifier, TK_Semi // default : default . default ;
]);
CheckTokensForLine('function default(default:default):default;', 8,
[ tkKey, tkSpace, tkIdentifier, // function default
TK_Bracket, tkIdentifier, TK_Colon, tkIdentifier, TK_Bracket, // ( default : default )
TK_Colon, tkIdentifier, TK_Semi // : default;
]);
CheckTokensForLine('function default(default:default.default):default.default;', 9,
[ tkKey, tkSpace, tkIdentifier, // function default
TK_Bracket, tkIdentifier, TK_Colon, // ( default :
tkIdentifier, TK_Dot, tkIdentifier, TK_Bracket, // default . default )
TK_Colon, tkIdentifier, TK_Dot, tkIdentifier, TK_Semi // : default . default;
]);
CheckTokensForLine('property default[default:default]:default read default write default; default;', 10,
[ tkKey, tkSpace, tkIdentifier, TK_Bracket, tkIdentifier, // property default[default
TK_Colon, tkIdentifier, TK_Bracket, TK_Colon, tkIdentifier, // :default]:default
tkSpace, tkKey, tkSpace, tkIdentifier, // read default
tkSpace, tkKey, tkSpace, tkIdentifier, // write default
TK_Semi, tkSpace, tkKey, TK_Semi // ; default;
]);
CheckTokensForLine('property default:default read default default default;', 11,
[ tkKey, tkSpace, tkIdentifier, TK_Colon, tkIdentifier, //property default:default
tkSpace, tkKey, tkSpace, tkIdentifier, // read default
tkSpace, tkKey, tkSpace, tkIdentifier, TK_Semi // default default;
]);
CheckTokensForLine('property default:default index default read default default default-default+default;', 12,
[ tkKey, tkSpace, tkIdentifier, TK_Colon, tkIdentifier, // property default:default
tkSpace, tkKey, tkSpace, tkIdentifier, // index default
tkSpace, tkKey, tkSpace, tkIdentifier, // read default
tkSpace, tkKey, tkSpace, tkIdentifier, // default default
tkSymbol, tkIdentifier, tkSymbol, tkIdentifier, TK_Semi // -default+default;
]);
CheckTokensForLine('property default:default.default index {C} default.default read {C} default.default {C} default default.default * default.default;', 13,
[ tkKey, tkSpace, tkIdentifier, TK_Colon, tkIdentifier, TK_Dot, tkIdentifier, // property default:default.default
tkSpace, tkKey, tkSpace, tkComment, tkSpace, // index (C}
tkIdentifier, TK_Dot, tkIdentifier, tkSpace, // default.default
tkKey, tkSpace, tkComment, tkSpace, // read (C}
tkIdentifier, TK_Dot, tkIdentifier, tkSpace, // default.default
tkComment, tkSpace, // (C}
tkKey, tkSpace, tkIdentifier, TK_Dot, tkIdentifier, tkSpace, // default default.default
tkSymbol, tkSpace, tkIdentifier, TK_Dot, tkIdentifier, TK_Semi // * default.default;
]);
{%endregion}
end;
procedure TTestHighlighterPas.TestContextForProcedure;