codetools: FindStartOfTerm: allow numbers and string constants, needed for type helpers

git-svn-id: trunk@50080 -
This commit is contained in:
mattias 2015-10-16 09:39:55 +00:00
parent 1125a0b930
commit de4a5aaa57
4 changed files with 119 additions and 42 deletions

2
.gitattributes vendored
View File

@ -1011,6 +1011,8 @@ components/codetools/tests/fpctests/tchlp53.pp svneol=native#text/plain
components/codetools/tests/fpctests/tchlp6.pp svneol=native#text/plain components/codetools/tests/fpctests/tchlp6.pp svneol=native#text/plain
components/codetools/tests/fpctests/tchlp7.pp svneol=native#text/plain components/codetools/tests/fpctests/tchlp7.pp svneol=native#text/plain
components/codetools/tests/laztests/README.txt svneol=native#text/plain components/codetools/tests/laztests/README.txt svneol=native#text/plain
components/codetools/tests/laztests/bug28861_unit1.pas svneol=native#text/plain
components/codetools/tests/laztests/bug28861_unit2.pas svneol=native#text/plain
components/codetools/tests/laztests/tdefaultproperty1.pas svneol=native#text/plain components/codetools/tests/laztests/tdefaultproperty1.pas svneol=native#text/plain
components/codetools/tests/parsertbase.pas svneol=native#text/plain components/codetools/tests/parsertbase.pas svneol=native#text/plain
components/codetools/tests/parsertest.lpi svneol=native#text/plain components/codetools/tests/parsertest.lpi svneol=native#text/plain

View File

@ -55,7 +55,7 @@ interface
{ $DEFINE ShowTriedParentContexts} { $DEFINE ShowTriedParentContexts}
{ $DEFINE ShowTriedIdentifiers} { $DEFINE ShowTriedIdentifiers}
{ $DEFINE ShowTriedUnits} { $DEFINE ShowTriedUnits}
{ $DEFINE ShowExprEval} {$DEFINE ShowExprEval}
{ $DEFINE ShowForInEval} { $DEFINE ShowForInEval}
{ $DEFINE ShowFoundIdentifier} { $DEFINE ShowFoundIdentifier}
{ $DEFINE ShowNodeCache} { $DEFINE ShowNodeCache}
@ -102,7 +102,9 @@ type
vatEdgedBracketOpen, // [ vatEdgedBracketOpen, // [
vatEdgedBracketClose,// ] vatEdgedBracketClose,// ]
vatAddrOp, // @ vatAddrOp, // @
vatKeyword // other keywords vatKeyword, // other keywords
vatNumber, // decimal, & octal, % binary, $ hex
vatStringConstant // '' or #
); );
const const
@ -121,7 +123,9 @@ const
'Bracket[', 'Bracket[',
'Bracket]', 'Bracket]',
'AddrOperator@ ', 'AddrOperator@ ',
'Keyword' 'Keyword',
'Number',
'StringConstant'
); );
type type
@ -3073,6 +3077,7 @@ function TFindDeclarationTool.FindDeclarationOfIdentAtParam(
Examples: Examples:
A^.B().C[].Identifier A^.B().C[].Identifier
inherited Identifier(p1,p2) inherited Identifier(p1,p2)
'Hello'.identifier
} }
var var
StartPos, EndPos: integer; StartPos, EndPos: integer;
@ -7601,6 +7606,7 @@ function TFindDeclarationTool.FindStartOfTerm(EndPos: integer; InType: boolean
9. (@A) 9. (@A)
10. A()[] 10. A()[]
11. nothing (e.g. cursor behind semicolon, keyword or closing bracket) 11. nothing (e.g. cursor behind semicolon, keyword or closing bracket)
12. 'A'.B (constant.B, type helpers)
} }
procedure RaiseIdentNotFound; procedure RaiseIdentNotFound;
begin begin
@ -7610,6 +7616,7 @@ function TFindDeclarationTool.FindStartOfTerm(EndPos: integer; InType: boolean
var CurAtom, NextAtom: TAtomPosition; var CurAtom, NextAtom: TAtomPosition;
NextAtomType, CurAtomType: TVariableAtomType; NextAtomType, CurAtomType: TVariableAtomType;
StartPos: LongInt; StartPos: LongInt;
CurIsValue, NextIsValue: Boolean;
begin begin
StartPos:=FindStartOfAtom(Src,EndPos); StartPos:=FindStartOfAtom(Src,EndPos);
MoveCursorToCleanPos(StartPos); MoveCursorToCleanPos(StartPos);
@ -7617,6 +7624,7 @@ begin
if not IsSpaceChar[Src[StartPos]] then if not IsSpaceChar[Src[StartPos]] then
ReadNextAtom; ReadNextAtom;
NextAtomType:=GetCurrentAtomType; NextAtomType:=GetCurrentAtomType;
NextIsValue:=NextAtomType in [vatIdentifier,vatPreDefIdentifier,vatNumber,vatStringConstant];
repeat repeat
ReadPriorAtom; ReadPriorAtom;
CurAtom:=CurPos; CurAtom:=CurPos;
@ -7651,14 +7659,13 @@ begin
Result:=NextAtom.StartPos; Result:=NextAtom.StartPos;
exit; exit;
end; end;
if (not (CurAtomType in [vatIdentifier,vatPreDefIdentifier,vatPoint,vatUp, CurIsValue:=CurAtomType in [vatIdentifier,vatPreDefIdentifier,vatNumber,vatStringConstant];
vatEdgedBracketClose,vatRoundBracketClose]))
or ((CurAtomType in [vatIdentifier,vatPreDefIdentifier,vatNone]) if (not (CurAtomType in [vatIdentifier,vatPreDefIdentifier,vatNumber,vatStringConstant,
and (NextAtomType in [vatIdentifier,vatPreDefIdentifier])) vatPoint,vatUp,vatEdgedBracketClose,vatRoundBracketClose]))
or ((CurAtomType in [vatNone]) or (CurIsValue and NextIsValue)
and (NextAtomType in [vatIdentifier,vatPreDefIdentifier,
vatRoundBracketClose]))
then begin then begin
// boundary found between current and next
if NextAtom.StartPos>=EndPos then begin if NextAtom.StartPos>=EndPos then begin
// no token belongs to a variable (e.g. ; ;) // no token belongs to a variable (e.g. ; ;)
Result:=EndPos; Result:=EndPos;
@ -7677,6 +7684,7 @@ begin
end; end;
NextAtom:=CurAtom; NextAtom:=CurAtom;
NextAtomType:=CurAtomType; NextAtomType:=CurAtomType;
NextIsValue:=CurIsValue;
until false; until false;
end; end;
@ -7705,8 +7713,8 @@ type
TIsIdentEndOfVar = (iieovYes, iieovNo, iieovUnknown); TIsIdentEndOfVar = (iieovYes, iieovNo, iieovUnknown);
var var
CurAtomType: TVariableAtomType; CurAtomType: TVariableAtomType;
NextAtomType: TVariableAtomType; // next, after any brackets NextAtomType: TVariableAtomType; // next, if CurAtomType is brackets then after the brackets
LastAtomType: TVariableAtomType; PrevAtomType: TVariableAtomType; // previous, start of brackets
CurAtom, NextAtom: TAtomPosition; CurAtom, NextAtom: TAtomPosition;
CurAtomBracketEndPos: integer; CurAtomBracketEndPos: integer;
StartNode: TCodeTreeNode; StartNode: TCodeTreeNode;
@ -7766,7 +7774,7 @@ var
{$IFDEF ShowExprEval} {$IFDEF ShowExprEval}
DebugLn([' FindExpressionTypeOfTerm InitAtomQueue StartPos=',StartPos,' EndPos=',EndPos,' Expr="',copy(Src,StartPos,EndPos-StartPos),'"']); DebugLn([' FindExpressionTypeOfTerm InitAtomQueue StartPos=',StartPos,' EndPos=',EndPos,' Expr="',copy(Src,StartPos,EndPos-StartPos),'"']);
{$ENDIF} {$ENDIF}
LastAtomType:=vatNone; PrevAtomType:=vatNone;
MoveCursorToCleanPos(StartPos); MoveCursorToCleanPos(StartPos);
ReadNextAtom; ReadNextAtom;
if CurPos.StartPos>SrcLen then exit; if CurPos.StartPos>SrcLen then exit;
@ -7789,7 +7797,7 @@ var
procedure ReadNextExpressionAtom; procedure ReadNextExpressionAtom;
begin begin
LastAtomType:=CurAtomType; PrevAtomType:=CurAtomType;
CurAtom:=NextAtom; CurAtom:=NextAtom;
CurAtomType:=NextAtomType; CurAtomType:=NextAtomType;
MoveCursorToCleanPos(NextAtom.StartPos); MoveCursorToCleanPos(NextAtom.StartPos);
@ -8499,7 +8507,7 @@ var
ReadNextAtom; ReadNextAtom;
RaiseIllegalQualifierFound; RaiseIllegalQualifierFound;
end; end;
if LastAtomType<>vatNone then begin if PrevAtomType<>vatNone then begin
// typecast or function // typecast or function
{$IFDEF ShowExprEval} {$IFDEF ShowExprEval}
debugln([' FindExpressionTypeOfTerm ResolveRoundBracketOpen skip typecast/paramlist="',dbgstr(Src,CurAtom.StartPos,CurAtomBracketEndPos-CurAtom.StartPos),'"']); debugln([' FindExpressionTypeOfTerm ResolveRoundBracketOpen skip typecast/paramlist="',dbgstr(Src,CurAtom.StartPos,CurAtomBracketEndPos-CurAtom.StartPos),'"']);
@ -9858,50 +9866,62 @@ end;
function TFindDeclarationTool.GetCurrentAtomType: TVariableAtomType; function TFindDeclarationTool.GetCurrentAtomType: TVariableAtomType;
var var
Node: TCodeTreeNode; Node: TCodeTreeNode;
c: Char;
begin begin
//debugln(['TFindDeclarationTool.GetCurrentAtomType ',CurPos.StartPos,' ',CurPos.EndPos,' ',SrcLen,' ',GetAtom]); //debugln(['TFindDeclarationTool.GetCurrentAtomType ',CurPos.StartPos,' ',CurPos.EndPos,' ',SrcLen,' ',GetAtom]);
if (CurPos.StartPos=CurPos.EndPos) then if (CurPos.StartPos=CurPos.EndPos) then
Result:=vatSpace exit(vatSpace)
else if (CurPos.StartPos<1) or (CurPos.StartPos>SrcLen) then else if (CurPos.StartPos<1) or (CurPos.StartPos>SrcLen) then
Result:=vatNone exit(vatNone);
else if IsIdentStartChar[Src[CurPos.StartPos]] then begin c:=Src[CurPos.StartPos];
if IsIdentStartChar[c] then begin
if WordIsPredefinedIdentifier.DoItCaseInsensitive(Src,CurPos.StartPos, if WordIsPredefinedIdentifier.DoItCaseInsensitive(Src,CurPos.StartPos,
CurPos.EndPos-CurPos.StartPos) then CurPos.EndPos-CurPos.StartPos) then
Result:=vatPreDefIdentifier exit(vatPreDefIdentifier)
else if UpAtomIs('INHERITED') then else if UpAtomIs('INHERITED') then
Result:=vatINHERITED exit(vatINHERITED)
else if UpAtomIs('AS') then else if UpAtomIs('AS') then
Result:=vatAS exit(vatAS)
else if WordIsKeyWord.DoItCaseInsensitive(Src,CurPos.StartPos, else if WordIsKeyWord.DoItCaseInsensitive(Src,CurPos.StartPos,
CurPos.EndPos-CurPos.StartPos) then CurPos.EndPos-CurPos.StartPos) then
Result:=vatKeyWord exit(vatKeyWord)
else if UpAtomIs('PROPERTY') then begin else if UpAtomIs('PROPERTY') then begin
Node:=FindDeepestNodeAtPos(CurPos.StartPos,false); Node:=FindDeepestNodeAtPos(CurPos.StartPos,false);
if (Node<>nil) and (Node.Desc in [ctnProperty,ctnPropertySection]) then if (Node<>nil) and (Node.Desc in [ctnProperty,ctnPropertySection]) then
Result:=vatKeyword exit(vatKeyword)
else else
Result:=vatIdentifier; exit(vatIdentifier);
end else end else
Result:=vatIdentifier; exit(vatIdentifier);
end else if (Src[CurPos.StartPos]='&') and (CurPos.StartPos<SrcLen) end else if (CurPos.StartPos=CurPos.EndPos-1) then begin
and IsIdentStartChar[Src[CurPos.StartPos+1]] then begin case c of
// &keyword '.': exit(vatPoint);
Result:=vatIdentifier; '^': exit(vatUp);
end '(': exit(vatRoundBracketOpen);
else if (CurPos.StartPos=CurPos.EndPos-1) then begin ')': exit(vatRoundBracketClose);
case Src[CurPos.StartPos] of '[': exit(vatEdgedBracketOpen);
'.': Result:=vatPoint; ']': exit(vatEdgedBracketClose);
'^': Result:=vatUp; '@': exit(vatAddrOp);
'(': Result:=vatRoundBracketOpen; else exit(vatNone);
')': Result:=vatRoundBracketClose;
'[': Result:=vatEdgedBracketOpen;
']': Result:=vatEdgedBracketClose;
'@': Result:=vatAddrOp;
else Result:=vatNone;
end; end;
end end
else else begin
Result:=vatNone; case c of
'''','#': exit(vatStringConstant);
'&':
begin
if (CurPos.StartPos+1=CurPos.EndPos) then exit(vatNone);
c:=Src[CurPos.StartPos+1];
if IsIdentStartChar[c] then begin
// &keyword
exit(vatIdentifier);
end else if IsNumberChar[c] then
exit(vatNumber) // octal
else exit(vatNone);
end;
else exit(vatNone);
end;
end;
end; end;
function TFindDeclarationTool.CreateParamExprListFromStatement( function TFindDeclarationTool.CreateParamExprListFromStatement(

View File

@ -0,0 +1,37 @@
unit bug268861_unit1;
{$mode delphi}
interface
{ TStringHelper }
type
TStringHelper = record helper for string
private
function GetTheLength: Integer;
public
function Twice: string;
function Thrice: string;
property TheLength: Integer read GetTheLength;
end;
implementation
function TStringHelper.GetTheLength: Integer;
begin
Result := Length(Self)
end;
function TStringHelper.Twice: string;
begin
Result := Self + Self;
end;
function TStringHelper.Thrice: string;
begin
Result := Self + Self + Self;
end;
end.

View File

@ -0,0 +1,18 @@
unit bug28861_unit2;
{$mode delphi}
interface
uses
bug268861_unit1;
implementation
begin
'Hello'.Twice{declaration:bug268861_unit1.TStringHelper.Twice};
'Hello'.Thrice{declaration:bug268861_unit1.TStringHelper.Thrice};
'Hello'.GetTheLength{declaration:bug268861_unit1.TStringHelper.GetTheLength};
'Hello'.{collectidentifiers:}
end.