mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-22 21:19:24 +02:00
codetools: fixed crash on searching in used namespaces
This commit is contained in:
parent
065994a7d1
commit
d6fd8ec102
@ -9740,7 +9740,10 @@ var
|
|||||||
function ResolveUseUnit(StartUseUnitNode: TCodeTreeNode): TCodeTreeNode;
|
function ResolveUseUnit(StartUseUnitNode: TCodeTreeNode): TCodeTreeNode;
|
||||||
// IsStart=true, NextAtomType=vatPoint,
|
// IsStart=true, NextAtomType=vatPoint,
|
||||||
// StartUseUnitNameNode.Desc=ctnUseUnit
|
// StartUseUnitNameNode.Desc=ctnUseUnit
|
||||||
// -> Find the longest namespaced used unit (ctnUseUnitNamespace,ctnUseUnitClearName)
|
// The first dotted identifier matches a name in one of the uses sections.
|
||||||
|
// If any uses section or the source name has namespaces the longest fitting wins.
|
||||||
|
// Note: the uses section names hide all identifiers in the used unit interfaces.
|
||||||
|
// -> Find the longest (namespaced) used unit (ctnUseUnitNamespace,ctnUseUnitClearName)
|
||||||
// or the source name (ctnIdentifier), that fits the start of the
|
// or the source name (ctnIdentifier), that fits the start of the
|
||||||
// current identifier a.b.c...
|
// current identifier a.b.c...
|
||||||
//
|
//
|
||||||
@ -9761,37 +9764,24 @@ var
|
|||||||
|
|
||||||
var
|
var
|
||||||
UseUnitNode, Node, BestNode: TCodeTreeNode;
|
UseUnitNode, Node, BestNode: TCodeTreeNode;
|
||||||
HasNamespace: Boolean;
|
Level, BestLevel: Integer;
|
||||||
Count, Level, BestLevel: Integer;
|
|
||||||
p: PChar;
|
p: PChar;
|
||||||
DottedIdentifier: String;
|
DottedIdentifier: String;
|
||||||
begin
|
begin
|
||||||
Result:=StartUseUnitNode.FirstChild;
|
Result:=StartUseUnitNode.FirstChild;
|
||||||
//debugln(['ResolveUsenit START ',NextAtomType,' ',StartUseUnitNode.DescAsString,' "',GetIdentifier(@Src[CurAtom.StartPos]),'"']);
|
if not HasNameSpaces then exit;
|
||||||
// find all candidates
|
|
||||||
Count:=0;
|
|
||||||
HasNamespace:=false;
|
|
||||||
UseUnitNode:=StartUseUnitNode;
|
|
||||||
repeat
|
|
||||||
if (UseUnitNode.FirstChild<>nil)
|
|
||||||
and CompareSrcIdentifiers(CurAtom.StartPos,UseUnitNode.StartPos) then begin
|
|
||||||
// found candidate
|
|
||||||
inc(Count);
|
|
||||||
//debugln(['ResolveUsenit candidate found']);
|
|
||||||
if UseUnitNode.FirstChild.Desc=ctnUseUnitNamespace then begin
|
|
||||||
HasNamespace:=true;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
UseUnitNode:=GetPrevUseUnit(UseUnitNode);
|
|
||||||
until UseUnitNode=nil;
|
|
||||||
//debugln(['ResolveUsenit CandidateCount=',Count,' HasNamespace=',HasNamespace]);
|
|
||||||
if not HasNamespace then exit;
|
|
||||||
|
|
||||||
|
DottedIdentifier:=GetIdentifier(@Src[CurAtom.StartPos]);
|
||||||
|
|
||||||
|
//debugln(['ResolveUseUnit START ',NextAtomType,' ',StartUseUnitNode.DescAsString,' "',GetIdentifier(@Src[CurAtom.StartPos]),'" Result=',Result.DescAsString]);
|
||||||
|
// find all candidates
|
||||||
|
|
||||||
|
BestNode:=nil;
|
||||||
|
BestLevel:=0;
|
||||||
// multiple uses start with this identifier -> collect candidates
|
// multiple uses start with this identifier -> collect candidates
|
||||||
//debugln(['ResolveUsenit collect candidates ...']);
|
//debugln(['ResolveUseUnit collect candidates ...']);
|
||||||
|
|
||||||
// read a.b.c...
|
// read a.b.c...
|
||||||
DottedIdentifier:=GetIdentifier(@Src[CurAtom.StartPos]);
|
|
||||||
MoveCursorToCleanPos(NextAtom.EndPos);
|
MoveCursorToCleanPos(NextAtom.EndPos);
|
||||||
Level:=1;
|
Level:=1;
|
||||||
repeat
|
repeat
|
||||||
@ -9801,12 +9791,10 @@ var
|
|||||||
DottedIdentifier:=DottedIdentifier+'.'+GetAtom;
|
DottedIdentifier:=DottedIdentifier+'.'+GetAtom;
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
until CurPos.Flag<>cafPoint;
|
until CurPos.Flag<>cafPoint;
|
||||||
//debugln(['ResolveUsenit DottedIdentifier="',DottedIdentifier,'"']);
|
//debugln(['ResolveUseUnit DottedIdentifier="',DottedIdentifier,'"']);
|
||||||
|
|
||||||
// find longest dotted unit name in uses and source name
|
// find longest dotted unit name in uses and source name
|
||||||
UseUnitNode:=StartUseUnitNode;
|
UseUnitNode:=StartUseUnitNode;
|
||||||
BestNode:=nil;
|
|
||||||
BestLevel:=0;
|
|
||||||
repeat
|
repeat
|
||||||
Node:=UseUnitNode.FirstChild; // ctnUseUnitNamespace or ctnUseUnitClearName
|
Node:=UseUnitNode.FirstChild; // ctnUseUnitNamespace or ctnUseUnitClearName
|
||||||
UseUnitNode:=GetPrevUseUnit(UseUnitNode);
|
UseUnitNode:=GetPrevUseUnit(UseUnitNode);
|
||||||
@ -9892,7 +9880,10 @@ var
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
Result:=BestNode;
|
Result:=BestNode;
|
||||||
if Result=nil then exit;
|
if Result=nil then begin
|
||||||
|
// ToDo: search in used interfaces
|
||||||
|
exit(nil);
|
||||||
|
end;
|
||||||
|
|
||||||
// Result is now a ctnUseUnit
|
// Result is now a ctnUseUnit
|
||||||
Result:=Result.FirstChild;
|
Result:=Result.FirstChild;
|
||||||
@ -10154,6 +10145,9 @@ var
|
|||||||
Params.Flags:=[fdfSearchInAncestors,fdfExceptionOnNotFound,fdfSearchInHelpers]
|
Params.Flags:=[fdfSearchInAncestors,fdfExceptionOnNotFound,fdfSearchInHelpers]
|
||||||
+(fdfGlobals*Params.Flags);
|
+(fdfGlobals*Params.Flags);
|
||||||
Params.ContextNode:=Context.Node;
|
Params.ContextNode:=Context.Node;
|
||||||
|
if Context.Node=nil then
|
||||||
|
RaiseException(20250101153139,'[TFindDeclarationTool.FindExpressionTypeOfTerm.ResolveIdentifier] internal error');
|
||||||
|
|
||||||
SearchForwardToo:=false;
|
SearchForwardToo:=false;
|
||||||
if Context.Node=StartNode then begin
|
if Context.Node=StartNode then begin
|
||||||
// there is no special context -> search in parent contexts too
|
// there is no special context -> search in parent contexts too
|
||||||
@ -10166,26 +10160,23 @@ var
|
|||||||
end else begin
|
end else begin
|
||||||
// only search in special context
|
// only search in special context
|
||||||
Params.Flags:=Params.Flags+[fdfIgnoreUsedUnits];
|
Params.Flags:=Params.Flags+[fdfIgnoreUsedUnits];
|
||||||
if Assigned(Context.Node) then begin
|
if Context.Node.Desc=ctnImplementation then
|
||||||
if (Context.Node.Desc=ctnImplementation) then
|
|
||||||
Params.Flags:=Params.Flags+[fdfSearchInParentNodes];
|
Params.Flags:=Params.Flags+[fdfSearchInParentNodes];
|
||||||
if (Context.Node.Desc=ctnObjCClass) then
|
if Context.Node.Desc=ctnObjCClass then
|
||||||
Exclude(Params.Flags,fdfExceptionOnNotFound); // ObjCClass has predefined identifiers like 'alloc'
|
Exclude(Params.Flags,fdfExceptionOnNotFound); // ObjCClass has predefined identifiers like 'alloc'
|
||||||
end;
|
end;
|
||||||
end;
|
|
||||||
|
|
||||||
// check identifier for overloaded procs
|
// check identifier for overloaded procs
|
||||||
if Assigned(Context.Node) then begin
|
|
||||||
if (IsEnd and (fdfIgnoreOverloadedProcs in StartFlags))
|
if (IsEnd and (fdfIgnoreOverloadedProcs in StartFlags))
|
||||||
then
|
then
|
||||||
Include(Params.Flags,fdfIgnoreOverloadedProcs);
|
Include(Params.Flags,fdfIgnoreOverloadedProcs);
|
||||||
//debugln(['ResolveIdentifier ',IsEnd,' ',GetAtom(CurAtom),' ',Context.Node.DescAsString,' ',Context.Node.Parent.DescAsString,' ']);
|
//debugln(['ResolveIdentifier ',IsEnd,' ',GetAtom(CurAtom),' ',Context.Node.DescAsString,' ',Context.Node.Parent.DescAsString,' ']);
|
||||||
if Assigned(Context.Node.Parent) and IsEnd and (Context.Node.Desc=ctnIdentifier)
|
if IsEnd and Assigned(Context.Node.Parent) and (Context.Node.Desc=ctnIdentifier)
|
||||||
and (Context.Node.Parent.Desc=ctnAttribParam)
|
and (Context.Node.Parent.Desc=ctnAttribParam)
|
||||||
and ResolveAttribute(Context) then begin
|
and ResolveAttribute(Context) then
|
||||||
|
begin
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
end;
|
|
||||||
|
|
||||||
Params.SetIdentifier(Self,@Src[CurAtom.StartPos],@CheckSrcIdentifier
|
Params.SetIdentifier(Self,@Src[CurAtom.StartPos],@CheckSrcIdentifier
|
||||||
{$IFDEF EnableFKnownIdentLength},FKnownIdentLength{$ENDIF});
|
{$IFDEF EnableFKnownIdentLength},FKnownIdentLength{$ENDIF});
|
||||||
@ -10239,9 +10230,15 @@ var
|
|||||||
// first identifier is a used unit -> find longest fitting unitname
|
// first identifier is a used unit -> find longest fitting unitname
|
||||||
//debugln(['ResolveIdentifier UseUnit FindLongest... ',Params.NewNode.DescAsString,' ',ExtractNode(Params.NewNode,[])]);
|
//debugln(['ResolveIdentifier UseUnit FindLongest... ',Params.NewNode.DescAsString,' ',ExtractNode(Params.NewNode,[])]);
|
||||||
Params.NewNode:=ResolveUseUnit(Params.NewNode.Parent);
|
Params.NewNode:=ResolveUseUnit(Params.NewNode.Parent);
|
||||||
|
// this might return nil!
|
||||||
//debugln(['ResolveIdentifier UseUnit FoundLongest: ',Params.NewNode.DescAsString,' ',ExtractNode(Params.NewNode,[])]);
|
//debugln(['ResolveIdentifier UseUnit FoundLongest: ',Params.NewNode.DescAsString,' ',ExtractNode(Params.NewNode,[])]);
|
||||||
end;
|
end;
|
||||||
ExprType.Context:=CreateFindContext(Params);
|
|
||||||
|
if Params.NewNode<>nil then
|
||||||
|
ExprType.Context:=CreateFindContext(Params)
|
||||||
|
else
|
||||||
|
ExprType.Desc:=xtNone;
|
||||||
|
|
||||||
Params.Load(OldInput,true);
|
Params.Load(OldInput,true);
|
||||||
end else begin
|
end else begin
|
||||||
// predefined identifier
|
// predefined identifier
|
||||||
|
@ -266,6 +266,7 @@ type
|
|||||||
ScannedRange: TLinkScannerRange; // excluding the section with a syntax error
|
ScannedRange: TLinkScannerRange; // excluding the section with a syntax error
|
||||||
ScanTill: TLinkScannerRange;
|
ScanTill: TLinkScannerRange;
|
||||||
AddedNameSpace: string; // program, library and package namespace
|
AddedNameSpace: string; // program, library and package namespace
|
||||||
|
HasNameSpaces: boolean; // the source name or a uses section uses namespaces
|
||||||
|
|
||||||
procedure ValidateToolDependencies; virtual;
|
procedure ValidateToolDependencies; virtual;
|
||||||
procedure BuildTree(Range: TLinkScannerRange);
|
procedure BuildTree(Range: TLinkScannerRange);
|
||||||
@ -796,6 +797,7 @@ begin
|
|||||||
if CurPos.Flag=cafPoint then begin
|
if CurPos.Flag=cafPoint then begin
|
||||||
if aNameSpace<>'' then aNameSpace:=aNameSpace+'.';
|
if aNameSpace<>'' then aNameSpace:=aNameSpace+'.';
|
||||||
aNameSpace:=aNameSpace+aName;
|
aNameSpace:=aNameSpace+aName;
|
||||||
|
HasNameSpaces:=true;
|
||||||
end else
|
end else
|
||||||
break;
|
break;
|
||||||
until false;
|
until false;
|
||||||
@ -2203,6 +2205,7 @@ begin
|
|||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
if CurPos.Flag<>cafPoint then break;
|
if CurPos.Flag<>cafPoint then break;
|
||||||
LastUnitNode.Desc:=ctnUseUnitNamespace;
|
LastUnitNode.Desc:=ctnUseUnitNamespace;
|
||||||
|
HasNameSpaces:=true;
|
||||||
ReadNextAtom;
|
ReadNextAtom;
|
||||||
AtomIsIdentifierSaveE(20180411194112);
|
AtomIsIdentifierSaveE(20180411194112);
|
||||||
until false;
|
until false;
|
||||||
@ -5699,6 +5702,8 @@ begin
|
|||||||
if Tree.Root<>nil then
|
if Tree.Root<>nil then
|
||||||
debugln(['TPascalParserTool.FetchScannerSource compiler clean all nodes, because compiler mode/values changed ',MainFilename]);
|
debugln(['TPascalParserTool.FetchScannerSource compiler clean all nodes, because compiler mode/values changed ',MainFilename]);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
AddedNameSpace:='';
|
||||||
|
HasNameSpaces:=false;
|
||||||
end else begin
|
end else begin
|
||||||
// find the first difference in source
|
// find the first difference in source
|
||||||
OldP:=PChar(Src);
|
OldP:=PChar(Src);
|
||||||
|
@ -489,7 +489,7 @@ begin
|
|||||||
while i>=0 do begin
|
while i>=0 do begin
|
||||||
IdentItem:=CodeToolBoss.IdentifierList.FilteredItems[i];
|
IdentItem:=CodeToolBoss.IdentifierList.FilteredItems[i];
|
||||||
if IdentItem.Node<>nil then begin
|
if IdentItem.Node<>nil then begin
|
||||||
FoundPath:=NodeAsPath(FoundTool,FoundNode);
|
FoundPath:=NodeAsPath(IdentItem.Tool,IdentItem.Node);
|
||||||
//debugln(['TTestFindDeclaration.FindDeclarations i=',i,' FoundPath="',FoundPath,'"']);
|
//debugln(['TTestFindDeclaration.FindDeclarations i=',i,' FoundPath="',FoundPath,'"']);
|
||||||
if SameText(ExpectedTerm,FoundPath) then
|
if SameText(ExpectedTerm,FoundPath) then
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user