mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-25 19:59:08 +02:00
codetools: FindFileAtCursor: unit name, search in comment
git-svn-id: trunk@53311 -
This commit is contained in:
parent
6e64d8a23d
commit
4eaf02c3a1
@ -1504,6 +1504,7 @@ end;
|
||||
function FindCommentEnd(const ASource: string; StartPos: integer;
|
||||
NestedComments: boolean): integer;
|
||||
// returns position after the comment end, e.g. after }
|
||||
// failure: returns length(ASource)+1
|
||||
var
|
||||
CommentLvl: integer;
|
||||
p: PChar;
|
||||
@ -2900,7 +2901,7 @@ begin
|
||||
else
|
||||
if Result>1 then begin
|
||||
c2:=Source[Result-1];
|
||||
// test for double char operators :=, +=, -=, /=, *=, <>, <=, >=, **, ><, ..
|
||||
// test for double char operators :=, +=, -=, /=, *=, <>, <=, >=, **, ><, @@ ..
|
||||
if ((c2='=') and (IsEqualOperatorStartChar[c]))
|
||||
or ((c='<') and (c2='>'))
|
||||
or ((c='>') and (c2='<'))
|
||||
|
@ -668,7 +668,8 @@ type
|
||||
ffatResource,
|
||||
ffatDisabledResource,
|
||||
ffatLiteral,
|
||||
ffatComment
|
||||
ffatComment,
|
||||
ffatUnit // unit by name
|
||||
);
|
||||
TFindFileAtCursorFlags = set of TFindFileAtCursorFlag;
|
||||
const
|
||||
@ -3560,10 +3561,71 @@ var
|
||||
end;
|
||||
end;
|
||||
|
||||
function CheckPlainComments(Source: string; CurAbsPos: integer): boolean;
|
||||
var
|
||||
Filename: String;
|
||||
p, EndPos, FileStartPos, FileEndPos, MinPos, MaxPos: Integer;
|
||||
begin
|
||||
// check if cursor in a comment (ignoring directives)
|
||||
Result:=false;
|
||||
CursorPos.Code.LineColToPosition(CursorPos.Y,CursorPos.X,CurAbsPos);
|
||||
Source:=CursorPos.Code.Source;
|
||||
if (CurAbsPos<1) or (CurAbsPos>length(Source)) then exit;
|
||||
p:=1;
|
||||
repeat
|
||||
p:=FindNextComment(Source,p);
|
||||
if p>CurAbsPos then break;
|
||||
EndPos:=FindCommentEnd(Source,p,Scanner.NestedComments);
|
||||
if EndPos>CurAbsPos then begin
|
||||
// cursor in comment
|
||||
MinPos:=p+1;
|
||||
MaxPos:=EndPos-1;
|
||||
if Source[p]<>'{' then begin
|
||||
inc(MinPos);
|
||||
dec(MaxPos);
|
||||
end;
|
||||
FileStartPos:=CurAbsPos;
|
||||
while (FileStartPos>MinPos) and not (Source[FileStartPos-1] in [#0..#32]) do
|
||||
dec(FileStartPos);
|
||||
FileEndPos:=CurAbsPos;
|
||||
while (FileEndPos<MaxPos) and not (Source[FileEndPos] in [#0..#32]) do
|
||||
inc(FileEndPos);
|
||||
Filename:=TrimFilename(copy(Source,FileStartPos,FileEndPos-FileStartPos));
|
||||
if not FilenameIsAbsolute(Filename) then
|
||||
Filename:=ResolveDots(ExtractFilePath(MainFilename)+Filename);
|
||||
if Scanner.OnLoadSource(Scanner,Filename,false)<>nil then begin
|
||||
Found:=ffatComment;
|
||||
FoundFilename:=Filename;
|
||||
exit(true);
|
||||
end;
|
||||
exit;
|
||||
end;
|
||||
p:=EndPos;
|
||||
until false;
|
||||
end;
|
||||
|
||||
function CheckUnitByWordAtCursor(Source: string; CurAbsPos: integer): boolean;
|
||||
// e.g. 'Sy|sUtils.CompareText'
|
||||
var
|
||||
AnUnitName: String;
|
||||
Code: TCodeBuffer;
|
||||
p: Integer;
|
||||
begin
|
||||
Result:=false;
|
||||
p:=FindStartOfAtom(Source,CurAbsPos);
|
||||
if p<1 then exit;
|
||||
AnUnitName:=GetIdentifier(@Source[p]);
|
||||
Code:=FindUnitSource(AnUnitName,'',false);
|
||||
if Code=nil then exit;
|
||||
Found:=ffatUnit;
|
||||
FoundFilename:=Code.Filename;
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
var
|
||||
CommentStart, CommentEnd, Col, StartCol: integer;
|
||||
CommentStart, CommentEnd, Col, StartCol, CurAbsPos: integer;
|
||||
Node: TCodeTreeNode;
|
||||
aUnitName, UnitInFilename, Line, Literal: string;
|
||||
aUnitName, UnitInFilename, Line, Literal, aSource: string;
|
||||
NewCode: TCodeBuffer;
|
||||
p, StartP: PChar;
|
||||
begin
|
||||
@ -3571,7 +3633,10 @@ begin
|
||||
Found:=ffatNone;
|
||||
FoundFilename:='';
|
||||
if StartPos<>nil then
|
||||
StartPos^:=CleanCodeXYPosition;
|
||||
StartPos^:=CleanCodeXYPosition;
|
||||
if CursorPos.Code.LineColIsOutside(CursorPos.Y,CursorPos.X) then exit;
|
||||
if CursorPos.Code.LineColIsSpace(CursorPos.Y,CursorPos.X) then exit;
|
||||
if (CursorPos.Y<1) or (CursorPos.Y>CursorPos.Code.LineCount) then exit;
|
||||
{$IFDEF VerboseFindFileAtCursor}
|
||||
debugln(['TFindDeclarationTool.FindFileAtCursor START']);
|
||||
{$ENDIF}
|
||||
@ -3663,42 +3728,52 @@ begin
|
||||
if ffatLiteral in SearchFor then begin
|
||||
// check literal
|
||||
p:=PChar(Line);
|
||||
Col:=1;
|
||||
repeat
|
||||
if p^=#0 then begin
|
||||
case p^ of
|
||||
#0:
|
||||
break;
|
||||
end else if p^='''' then begin
|
||||
StartCol:=Col;
|
||||
inc(Col);
|
||||
inc(p);
|
||||
StartP:=p;
|
||||
repeat
|
||||
case p^ of
|
||||
#0: break;
|
||||
'''': break;
|
||||
#9: Col:=(Col+8) and not 7;
|
||||
else inc(p,UTF8CharacterLength(p));
|
||||
end;
|
||||
until false;
|
||||
if (CursorPos.X>=StartCol) and (CursorPos.X<=Col) then begin
|
||||
Literal:=copy(Line,Col,p-StartP);
|
||||
if not FilenameIsAbsolute(Literal) then
|
||||
Literal:=TrimFilename(ExtractFilePath(Scanner.MainFilename)+Literal);
|
||||
if FilenameIsAbsolute(Literal)
|
||||
and DirectoryCache.Pool.FileExists(Literal) then begin
|
||||
'''':
|
||||
begin
|
||||
StartCol:=p-PChar(Line)+1;
|
||||
inc(p);
|
||||
StartP:=p;
|
||||
repeat
|
||||
case p^ of
|
||||
#0,'''': break;
|
||||
else inc(p);
|
||||
end;
|
||||
until false;
|
||||
Col:=p-PChar(Line)+1;
|
||||
writeln('TFindDeclarationTool.FindFileAtCursor Col=',Col,' CursorCol=',CursorPos.X,' Literal=',copy(Line,StartCol+1,p-StartP));
|
||||
if (p>StartP) and (CursorPos.X>=StartCol) and (CursorPos.X<=Col) then begin
|
||||
Literal:=copy(Line,StartCol+1,p-StartP);
|
||||
if not FilenameIsAbsolute(Literal) then
|
||||
Literal:=TrimFilename(ExtractFilePath(Scanner.MainFilename)+Literal);
|
||||
Found:=ffatLiteral;
|
||||
FoundFilename:=Literal;
|
||||
exit(true);
|
||||
end;
|
||||
if p^=#0 then break;
|
||||
// p is now on the ending '
|
||||
end;
|
||||
if p^=#0 then break;
|
||||
end;
|
||||
inc(p);
|
||||
inc(Col);
|
||||
until false;
|
||||
end;
|
||||
|
||||
// search without node tree with basic tools
|
||||
CursorPos.Code.LineColToPosition(CursorPos.Y,CursorPos.X,CurAbsPos);
|
||||
aSource:=CursorPos.Code.Source;
|
||||
if (CurAbsPos<1) or (CurAbsPos>length(aSource)) then exit;
|
||||
|
||||
if ffatComment in SearchFor then begin
|
||||
// ToDo: check simple
|
||||
// ignore syntax and only read comments
|
||||
if CheckPlainComments(aSource,CurAbsPos) then exit(true);
|
||||
end;
|
||||
|
||||
if ffatUnit in SearchFor then begin
|
||||
if CheckUnitByWordAtCursor(aSource,CurAbsPos) then exit(true);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -57,7 +57,6 @@ type
|
||||
|
||||
procedure ExtendXmlDocument(Doc: TXMLDocument); override;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
end;
|
||||
|
||||
@ -142,16 +141,11 @@ begin
|
||||
Doc.FirstChild.AppendChild(env);
|
||||
end;
|
||||
|
||||
constructor TCTTestRunner.Create(AOwner: TComponent);
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
DefaultFormat:=fPlain;
|
||||
DefaultRunAllTests:=true;
|
||||
end;
|
||||
|
||||
var
|
||||
App: TCTTestRunner;
|
||||
begin
|
||||
DefaultFormat:=fPlain;
|
||||
DefaultRunAllTests:=True;
|
||||
App := TCTTestRunner.Create(nil);
|
||||
App.Initialize;
|
||||
App.Title := 'FPCUnit Console runner for the CodeTools Find Declaration Suite.';
|
||||
|
@ -402,17 +402,36 @@ begin
|
||||
AssertEquals('FindFileAtCursor in literal Found',ord(ffatLiteral),ord(Found));
|
||||
AssertEquals('FindFileAtCursor in literal FoundFilename','unit2.pas',FoundFilename);
|
||||
|
||||
// --- comment ---
|
||||
Code.Source:='program test1;'+LineEnding
|
||||
+'{unit2.pas}'+LineEnding;
|
||||
if not CodeToolBoss.FindFileAtCursor(Code,3,2,Found,FoundFilename) then
|
||||
Fail('CodeToolBoss.FindFileAtCursor in comment');
|
||||
AssertEquals('FindFileAtCursor in comment Found',ord(ffatComment),ord(Found));
|
||||
AssertEquals('FindFileAtCursor in comment FoundFilename','unit2.pas',FoundFilename);
|
||||
|
||||
// --- unit name search in comment ---
|
||||
Code.Source:='program test1;'+LineEnding
|
||||
+'{unit2}'+LineEnding;
|
||||
if not CodeToolBoss.FindFileAtCursor(Code,3,2,Found,FoundFilename) then
|
||||
Fail('CodeToolBoss.FindFileAtCursor in comment');
|
||||
AssertEquals('FindFileAtCursor in comment Found',ord(ffatUnit),ord(Found));
|
||||
AssertEquals('FindFileAtCursor in comment FoundFilename','unit2.pas',FoundFilename);
|
||||
|
||||
// --- unit name search in code ---
|
||||
Code.Source:='program test1;'+LineEnding
|
||||
+'begin'+LineEnding
|
||||
+' unit2.Test;'+LineEnding;
|
||||
if not CodeToolBoss.FindFileAtCursor(Code,3,3,Found,FoundFilename) then
|
||||
Fail('CodeToolBoss.FindFileAtCursor in comment');
|
||||
AssertEquals('FindFileAtCursor in comment Found',ord(ffatUnit),ord(Found));
|
||||
AssertEquals('FindFileAtCursor in comment FoundFilename','unit2.pas',FoundFilename);
|
||||
|
||||
finally
|
||||
Code.IsDeleted:=true;
|
||||
SubUnit2Code.IsDeleted:=true;
|
||||
LFMCode.IsDeleted:=true;
|
||||
end;
|
||||
// ToDo: test $i 'file with spaces' in code
|
||||
// ToDo: test $i in disabled code
|
||||
// ToDo: test 'readme.txt' in active code
|
||||
// ToDo: test readme.txt in active code fails
|
||||
// ToDo: test readme.txt in comment works
|
||||
end;
|
||||
|
||||
procedure TTestFindDeclaration.TestFindDeclaration_FPCTests;
|
||||
|
Loading…
Reference in New Issue
Block a user