mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-01 01:12:42 +02:00
codetools: refactored
git-svn-id: trunk@29297 -
This commit is contained in:
parent
a43e91a50a
commit
d900d21d44
@ -2511,75 +2511,102 @@ function FindLineEndOrCodeInFrontOfPosition(const Source: string;
|
||||
2: a:=1;
|
||||
|
||||
1: b:=1; |
|
||||
2: // comment
|
||||
3: // comment
|
||||
2: // comment for below
|
||||
3: // comment for below
|
||||
4: a:=1;
|
||||
|
||||
1: |
|
||||
2: /* */
|
||||
2: (* comment belongs to the following line *)
|
||||
3: a:=1;
|
||||
|
||||
1: end;| /*
|
||||
2: */ a:=1;
|
||||
1: end; (* comment belongs to the first line
|
||||
2: *)| a:=1;
|
||||
|
||||
1: b:=1; // comment |
|
||||
2: a:=1;
|
||||
|
||||
1: b:=1; /*
|
||||
2: comment */ |
|
||||
1: b:=1; (*
|
||||
2: comment *) |
|
||||
3: a:=1;
|
||||
}
|
||||
var SrcStart: integer;
|
||||
|
||||
function ReadComment(var P: integer; SubComment: boolean): boolean;
|
||||
function IsSpace(c: char): boolean;
|
||||
begin
|
||||
if SkipSemicolonComma then
|
||||
Result:=c in [' ',#9,';',',']
|
||||
else
|
||||
Result:=c in [' ',#9];
|
||||
end;
|
||||
|
||||
function ReadComment(var p: integer; SubComment: boolean): boolean;
|
||||
// true if comment was skipped
|
||||
// false if not skipped, because comment is compiler directive
|
||||
// false if not skipped, because comment is compiler directive or simple bracket
|
||||
var OldP: integer;
|
||||
IsDirective: Boolean;
|
||||
begin
|
||||
//debugln(['ReadComment ',dbgstr(copy(Source,p-5,5))+'|'+Source[P]+dbgstr(copy(Source,p+1,5))]);
|
||||
OldP:=P;
|
||||
IsDirective:=false;
|
||||
case Source[P] of
|
||||
'}':
|
||||
begin
|
||||
dec(P);
|
||||
while (P>=SrcStart) and (Source[P]<>'{') do begin
|
||||
if NestedComments and (Source[P]='}') then
|
||||
ReadComment(P,true)
|
||||
else
|
||||
dec(P);
|
||||
end;
|
||||
IsDirective:=(P>=SrcStart) and (Source[P+1]='$');
|
||||
dec(P);
|
||||
end;
|
||||
')':
|
||||
begin
|
||||
dec(P);
|
||||
if (P>=SrcStart) and (Source[P]='*') then begin
|
||||
dec(P);
|
||||
while (P>SrcStart)
|
||||
and ((Source[P-1]<>'(') or (Source[P]<>'*')) do begin
|
||||
if NestedComments and ((Source[P]=')') and (Source[P-1]='*')) then
|
||||
ReadComment(P,true)
|
||||
//debugln(['ReadComment ',dbgstr(copy(Source,p-5,5))+'|'+Source[p]+dbgstr(copy(Source,p+1,5))]);
|
||||
OldP:=p+1;
|
||||
repeat
|
||||
IsDirective:=false;
|
||||
case Source[p] of
|
||||
'}':
|
||||
begin
|
||||
dec(p);
|
||||
while (p>SrcStart) and (Source[p]<>'{') do begin
|
||||
if NestedComments and (Source[p]='}') then
|
||||
ReadComment(p,true)
|
||||
else
|
||||
dec(P);
|
||||
dec(p);
|
||||
end;
|
||||
IsDirective:=(P>=SrcStart) and (Source[P+1]='$');
|
||||
dec(P,2);
|
||||
end else begin
|
||||
// normal bracket
|
||||
// => position behind code
|
||||
inc(p);
|
||||
Result:=false;
|
||||
exit;
|
||||
IsDirective:=(p>=SrcStart) and (Source[p+1]='$');
|
||||
dec(p);
|
||||
end;
|
||||
end;
|
||||
else
|
||||
exit(true);
|
||||
end;
|
||||
Result:=(not IsDirective) or (not StopAtDirectives) or SubComment;
|
||||
if not Result then P:=OldP+1;
|
||||
')':
|
||||
begin
|
||||
dec(p);
|
||||
if (p>SrcStart) and (Source[p]='*') then begin
|
||||
dec(p);
|
||||
while (p>SrcStart)
|
||||
and ((Source[p-1]<>'(') or (Source[p]<>'*')) do begin
|
||||
if NestedComments and ((Source[p]=')') and (Source[p-1]='*')) then
|
||||
ReadComment(p,true)
|
||||
else
|
||||
dec(p);
|
||||
end;
|
||||
IsDirective:=(p>=SrcStart) and (Source[p+1]='$');
|
||||
dec(p,2);
|
||||
end else begin
|
||||
// normal bracket
|
||||
// => position behind code
|
||||
p:=OldP;
|
||||
exit(false);
|
||||
end;
|
||||
end;
|
||||
else
|
||||
exit(true);
|
||||
end;
|
||||
if SubComment then exit(true); // always skip nested comments
|
||||
if IsDirective and StopAtDirectives then begin
|
||||
// directive can not be skipped
|
||||
p:=OldP;
|
||||
exit(false);
|
||||
end;
|
||||
// it is a normal comment
|
||||
// check if it belongs to the code in front
|
||||
while (p>=SrcStart) and IsSpace(Source[p]) do
|
||||
dec(p);
|
||||
if (p<SrcStart) or (Source[p] in [#10,#13]) then begin
|
||||
// empty line in front of comment => comment can be skipped
|
||||
exit(true);
|
||||
end;
|
||||
if not (Source[p] in [')','}']) then begin
|
||||
// code => comment belongs to code in front
|
||||
p:=OldP;
|
||||
exit(false);
|
||||
end;
|
||||
// read next comment
|
||||
until false;
|
||||
end;
|
||||
|
||||
var
|
||||
@ -2587,46 +2614,47 @@ var
|
||||
LineStartPos: LongInt;
|
||||
IsEmpty: Boolean;
|
||||
LineEndPos: Integer;
|
||||
p: LongInt;
|
||||
begin
|
||||
SrcStart:=MinPosition;
|
||||
if SrcStart<1 then SrcStart:=1;
|
||||
if Position<=SrcStart then begin
|
||||
if (Position<=SrcStart) then begin
|
||||
Result:=SrcStart;
|
||||
exit;
|
||||
end;
|
||||
// simple heuristic
|
||||
// will fail on lines: // }
|
||||
Result:=Position-1;
|
||||
if Result>length(Source) then Result:=length(Source);
|
||||
while (Result>=SrcStart) do begin
|
||||
case Source[Result] of
|
||||
'}',')':
|
||||
if not ReadComment(Result,false) then exit;
|
||||
|
||||
// will fail on lines: // }
|
||||
Result:=-1;
|
||||
p:=Position-1;
|
||||
if p>length(Source) then p:=length(Source);
|
||||
while (p>=SrcStart) do begin
|
||||
case Source[p] of
|
||||
#10,#13:
|
||||
begin
|
||||
// line end in code found
|
||||
if (Result>SrcStart) and (Source[Result-1] in [#10,#13])
|
||||
and (Source[Result]<>Source[Result-1]) then
|
||||
dec(Result);
|
||||
LineEndPos:=Result; // start of line end
|
||||
// line end found (outside comments)
|
||||
if (p>SrcStart) and (Source[p-1] in [#10,#13])
|
||||
and (Source[p]<>Source[p-1]) then
|
||||
dec(p);
|
||||
LineEndPos:=p; // start of line end
|
||||
Result:=LineEndPos;
|
||||
// test if in a // comment
|
||||
LineStartPos:=Result;
|
||||
LineStartPos:=p;
|
||||
IsEmpty:=true;
|
||||
while (LineStartPos>SrcStart) do begin
|
||||
case Source[LineStartPos-1] of
|
||||
#10,#13: break;
|
||||
' ',#9: ;
|
||||
';',',': if not SkipSemicolonComma then IsEmpty:=false;
|
||||
else IsEmpty:=false;
|
||||
end;
|
||||
dec(LineStartPos);
|
||||
end;
|
||||
if IsEmpty then begin
|
||||
// the line is empty => return start of line end
|
||||
Result:=LineEndPos;
|
||||
p:=LineEndPos;
|
||||
if SkipEmptyLines then begin
|
||||
// skip all empty lines
|
||||
LineStartPos:=Result;
|
||||
LineStartPos:=p;
|
||||
while (LineStartPos>SrcStart) do begin
|
||||
case Source[LineStartPos-1] of
|
||||
#10,#13:
|
||||
@ -2636,7 +2664,7 @@ begin
|
||||
if (LineEndPos>SrcStart) and (Source[LineEndPos-1] in [#10,#13])
|
||||
and (Source[LineEndPos]<>Source[LineEndPos-1]) then
|
||||
dec(LineEndPos);
|
||||
Result:=LineEndPos;
|
||||
p:=LineEndPos;
|
||||
end;
|
||||
' ',#9: ;
|
||||
else
|
||||
@ -2646,37 +2674,41 @@ begin
|
||||
dec(LineStartPos);
|
||||
end;
|
||||
end;
|
||||
exit;
|
||||
break;
|
||||
end;
|
||||
// line is not empty
|
||||
TestPos:=LineStartPos;
|
||||
while (Source[TestPos] in [' ',#9]) do inc(TestPos);
|
||||
if (Source[TestPos]='/') and (Source[TestPos+1]='/') then begin
|
||||
// the whole line is a // comment
|
||||
// this comment belongs to the code
|
||||
// this comment belongs to the code behind
|
||||
// => continue on next line
|
||||
Result:=LineStartPos-1;
|
||||
p:=LineStartPos-1;
|
||||
continue;
|
||||
end;
|
||||
dec(Result);
|
||||
dec(p);
|
||||
end;
|
||||
|
||||
'}',')':
|
||||
if not ReadComment(p,false) then break;
|
||||
' ',#9:
|
||||
dec(Result);
|
||||
dec(p);
|
||||
';',',':
|
||||
begin
|
||||
if StopAtDirectives then begin
|
||||
if not SkipSemicolonComma then begin
|
||||
// code found
|
||||
inc(Result);
|
||||
exit;
|
||||
inc(p);
|
||||
break;
|
||||
end;
|
||||
dec(Result);
|
||||
dec(p);
|
||||
end;
|
||||
else
|
||||
// code found
|
||||
inc(Result);
|
||||
exit;
|
||||
inc(p);
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
if Result<1 then Result:=p;
|
||||
if Result<SrcStart then Result:=SrcStart;
|
||||
end;
|
||||
|
||||
|
@ -267,6 +267,7 @@ type
|
||||
function FindFirstPosition: integer;
|
||||
function FindLastPosition: integer;
|
||||
function ContainsNode(ANode: TCodeTreeNode): boolean;
|
||||
function FindRootNode(Desc: TCodeTreeNodeDesc): TCodeTreeNode;
|
||||
procedure Clear;
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
@ -923,6 +924,13 @@ begin
|
||||
Result:=ANode=Root;
|
||||
end;
|
||||
|
||||
function TCodeTree.FindRootNode(Desc: TCodeTreeNodeDesc): TCodeTreeNode;
|
||||
begin
|
||||
Result:=Root;
|
||||
while (Result<>nil) and (Result.Desc<>Desc) do
|
||||
Result:=Result.NextBrother;
|
||||
end;
|
||||
|
||||
procedure TCodeTree.ConsistencyCheck;
|
||||
var RealNodeCount: integer;
|
||||
|
||||
|
@ -246,6 +246,7 @@ type
|
||||
function FindPrevNodeOnSameLvl(StartNode: TCodeTreeNode): TCodeTreeNode;
|
||||
|
||||
// sections
|
||||
function FindRootNode(Desc: TCodeTreeNodeDesc): TCodeTreeNode;
|
||||
function FindInterfaceNode: TCodeTreeNode;
|
||||
function FindImplementationNode: TCodeTreeNode;
|
||||
function FindInitializationNode: TCodeTreeNode;
|
||||
@ -4665,6 +4666,12 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPascalParserTool.FindRootNode(Desc: TCodeTreeNodeDesc
|
||||
): TCodeTreeNode;
|
||||
begin
|
||||
Result:=Tree.FindRootNode(Desc);
|
||||
end;
|
||||
|
||||
function TPascalParserTool.NodeHasParentOfType(ANode: TCodeTreeNode;
|
||||
NodeDesc: TCodeTreeNodeDesc): boolean;
|
||||
begin
|
||||
@ -5119,30 +5126,22 @@ end;
|
||||
|
||||
function TPascalParserTool.FindInterfaceNode: TCodeTreeNode;
|
||||
begin
|
||||
Result:=Tree.Root;
|
||||
while (Result<>nil) and (Result.Desc<>ctnInterface) do
|
||||
Result:=Result.NextBrother;
|
||||
Result:=FindRootNode(ctnInterface);
|
||||
end;
|
||||
|
||||
function TPascalParserTool.FindImplementationNode: TCodeTreeNode;
|
||||
begin
|
||||
Result:=Tree.Root;
|
||||
while (Result<>nil) and (Result.Desc<>ctnImplementation) do
|
||||
Result:=Result.NextBrother;
|
||||
Result:=FindRootNode(ctnImplementation);
|
||||
end;
|
||||
|
||||
function TPascalParserTool.FindInitializationNode: TCodeTreeNode;
|
||||
begin
|
||||
Result:=Tree.Root;
|
||||
while (Result<>nil) and (Result.Desc<>ctnInitialization) do
|
||||
Result:=Result.NextBrother;
|
||||
Result:=FindRootNode(ctnInitialization);
|
||||
end;
|
||||
|
||||
function TPascalParserTool.FindFinalizationNode: TCodeTreeNode;
|
||||
begin
|
||||
Result:=Tree.Root;
|
||||
while (Result<>nil) and (Result.Desc<>ctnFinalization) do
|
||||
Result:=Result.NextBrother;
|
||||
Result:=FindRootNode(ctnFinalization);
|
||||
end;
|
||||
|
||||
function TPascalParserTool.FindMainBeginEndNode: TCodeTreeNode;
|
||||
|
Loading…
Reference in New Issue
Block a user