From 995c81f4d0de5f40ea1516d9dc691e3ead86e025 Mon Sep 17 00:00:00 2001 From: mattias Date: Mon, 10 Feb 2025 15:31:45 +0100 Subject: [PATCH] codetools: added IdentifierHasKeywords --- components/codetools/codetoolmanager.pas | 9 +++++ components/codetools/customcodetool.pas | 40 +++++++++++++++++++ components/codetools/multikeywordlisttool.pas | 1 - .../codetools/tests/testrefactoring.pas | 30 ++++++++++++-- 4 files changed, 76 insertions(+), 4 deletions(-) diff --git a/components/codetools/codetoolmanager.pas b/components/codetools/codetoolmanager.pas index 33b4831857..520877eb2c 100644 --- a/components/codetools/codetoolmanager.pas +++ b/components/codetools/codetoolmanager.pas @@ -470,6 +470,8 @@ type KeepVerbosityDirectives: boolean = false): string; function GetPasDocComments(Code: TCodeBuffer; X, Y: integer; out ListOfPCodeXYPosition: TFPList): boolean; + function IdentifierHasKeywords(const Identifier, Directory: string; + out AmpIdentifier: string): boolean; // blocks (e.g. begin..end, case..end, try..finally..end, repeat..until) function FindBlockCounterPart(Code: TCodeBuffer; X,Y: integer; @@ -4208,6 +4210,13 @@ begin {$ENDIF} end; +function TCodeToolManager.IdentifierHasKeywords(const Identifier, Directory: string; out + AmpIdentifier: string): boolean; +begin + Result:=CustomCodeTool.IdentifierHasKeywords(Identifier, + GetCompilerModeForDirectory(Directory),AmpIdentifier); +end; + function TCodeToolManager.FindBlockCounterPart(Code: TCodeBuffer; X, Y: integer; out NewCode: TCodeBuffer; out NewX, NewY, NewTopLine: integer; IncludeCloseToken: Boolean): boolean; diff --git a/components/codetools/customcodetool.pas b/components/codetools/customcodetool.pas index fde81044c2..b1554cc087 100644 --- a/components/codetools/customcodetool.pas +++ b/components/codetools/customcodetool.pas @@ -352,6 +352,9 @@ var function CompareCodeTreeNodeParserError(Error1, Error2: Pointer): integer; function CompareNodeWithCodeTreeNodeParserError(Node, Error: Pointer): integer; +function IdentifierHasKeywords(const Identifier: string; cm: TCompilerMode; out + AmpIdentifier: string): boolean; + implementation function CompareCodeTreeNodeParserError(Error1, Error2: Pointer): integer; @@ -369,6 +372,43 @@ begin Result:=ComparePointers(Node,AnError.Node); end; +function IdentifierHasKeywords(const Identifier: string; cm: TCompilerMode; out + AmpIdentifier: string): boolean; +var + p, StartP: Integer; + KeyWords: TKeyWordFunctionList; +begin + Result:=false; + AmpIdentifier:=Identifier; + Keywords:=nil; + p:=length(Identifier); + while p>0 do begin + while (p>0) and IsIdentChar[Identifier[p]] do dec(p); + if (p>0) and (Identifier[p]='&') then begin + // &name -> ok + end else begin + inc(p); + if Keywords=nil then begin + case cm of + cmMacPas: KeyWords:=KeywordFuncLists.WordIsMacPasKeyWord; + cmDELPHI, cmDELPHIUNICODE: KeyWords:=KeywordFuncLists.WordIsDelphiKeyWord; + else + KeyWords:=KeywordFuncLists.WordIsKeyWord; + end; + end; + if KeyWords.DoIdentifier(@Identifier[p]) then begin + System.Insert('&',AmpIdentifier,p); + Result:=true; + end; + end; + dec(p); + if (p>0) and (Identifier[p]='.') then + dec(p) + else + exit; + end; +end; + { TCustomCodeTool } constructor TCustomCodeTool.Create; diff --git a/components/codetools/multikeywordlisttool.pas b/components/codetools/multikeywordlisttool.pas index 0dfd7e2293..017a1c00d7 100644 --- a/components/codetools/multikeywordlisttool.pas +++ b/components/codetools/multikeywordlisttool.pas @@ -63,7 +63,6 @@ type procedure CalcMemSize(Stats: TCTMemStats); override; end; - implementation { TMultiKeyWordListCodeTool } diff --git a/components/codetools/tests/testrefactoring.pas b/components/codetools/tests/testrefactoring.pas index 5d3f1266f9..a67c8547bf 100644 --- a/components/codetools/tests/testrefactoring.pas +++ b/components/codetools/tests/testrefactoring.pas @@ -13,7 +13,7 @@ uses Classes, SysUtils, Contnrs, fpcunit, AVL_Tree, LazLogger, LazFileUtils, testregistry, CodeToolManager, CodeCache, CodeTree, BasicCodeTools, CTUnitGraph, - FindDeclarationTool, ChangeDeclarationTool, TestGlobals, + FindDeclarationTool, ChangeDeclarationTool, CustomCodeTool, LinkScanner, TestGlobals, TestFinddeclaration; const @@ -39,8 +39,10 @@ type protected published procedure TestExplodeWith; - procedure TestRenameReferences; + procedure TestIdentifierHasKeywords; + + procedure TestRenameVarReferences; procedure TestRenameProcReferences; procedure TestRenameProcedureArg; procedure TestRenameProcedureArgCaseSensitive; @@ -423,7 +425,29 @@ begin end; end; -procedure TTestRefactoring.TestRenameReferences; +procedure TTestRefactoring.TestIdentifierHasKeywords; + + procedure t(const Identifier: string; + cm: TCompilerMode; const ExpectedAmp: string); + var + AmpIdentifier: string; + r: Boolean; + begin + r:=IdentifierHasKeywords(Identifier, cm, AmpIdentifier); + if AmpIdentifier<>ExpectedAmp then + Fail('Identifier="'+Identifier+'" cm='+CompilerModeNames[cm]+' expected "'+ExpectedAmp+'", but got "'+AmpIdentifier+'"'); + AssertEquals('Result',Identifier<>AmpIdentifier,r); + end; + +begin + t('a',cmFPC,'a'); + t('a.b',cmFPC,'a.b'); + t('a.&b',cmFPC,'a.&b'); + t('a.Type',cmFPC,'a.&Type'); + t('End.Type',cmFPC,'&End.&Type'); +end; + +procedure TTestRefactoring.TestRenameVarReferences; begin StartProgram; Add([