mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-01 22:12:40 +02:00
codetools: class completion: check if vars exists ancestors, bug #1189, patch from Ondrej Pokorny
git-svn-id: trunk@50006 -
This commit is contained in:
parent
db1651b90f
commit
4f6fa03e6f
@ -445,7 +445,12 @@ function TCodeCompletionCodeTool.ProcExistsInCodeCompleteClass(
|
||||
// NameAndParams should be uppercase and contains the proc name and the
|
||||
// parameter list without names and default values
|
||||
// and should not contain any comments and no result type
|
||||
var ANodeExt: TCodeTreeNodeExtension;
|
||||
var
|
||||
ANodeExt: TCodeTreeNodeExtension;
|
||||
Params: TFindDeclarationParams;
|
||||
ClassNode, CompletingChildNode: TCodeTreeNode;
|
||||
Tool: TFindDeclarationTool;
|
||||
Vis: TClassSectionVisibility;
|
||||
begin
|
||||
Result:=false;
|
||||
// search in new nodes, which will be inserted
|
||||
@ -455,9 +460,29 @@ begin
|
||||
exit(true);
|
||||
ANodeExt:=ANodeExt.Next;
|
||||
end;
|
||||
// ToDo: check ancestor procs too
|
||||
// search in current class
|
||||
Result:=(FindProcNode(FCompletingFirstEntryNode,NameAndParamsUpCase,mgMethod,[phpInUpperCase])<>nil);
|
||||
if not Result then
|
||||
begin
|
||||
//search in ancestor classes
|
||||
Params:=TFindDeclarationParams.Create;
|
||||
try
|
||||
ClassNode:=CodeCompleteClassNode;
|
||||
Tool:=Self;
|
||||
while not Result and Tool.FindAncestorOfClass(ClassNode,Params,True) do begin
|
||||
Tool:=Params.NewCodeTool;
|
||||
ClassNode:=Params.NewNode;
|
||||
CompletingChildNode:=GetFirstClassIdentifier(ClassNode);
|
||||
if Tool=Self then
|
||||
Vis := csvPrivateAndHigher
|
||||
else
|
||||
Vis := csvProtectedAndHigher;
|
||||
Result := (Tool.FindProcNode(CompletingChildNode,NameAndParamsUpCase,mgMethod,[phpInUpperCase], Vis)<>nil);
|
||||
end;
|
||||
finally
|
||||
Params.Free;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCodeCompletionCodeTool.SetCodeCompleteClassNode(const AClassNode: TCodeTreeNode);
|
||||
@ -556,7 +581,12 @@ end;
|
||||
|
||||
function TCodeCompletionCodeTool.VarExistsInCodeCompleteClass(
|
||||
const UpperName: string): boolean;
|
||||
var ANodeExt: TCodeTreeNodeExtension;
|
||||
var
|
||||
ANodeExt: TCodeTreeNodeExtension;
|
||||
Params: TFindDeclarationParams;
|
||||
ClassNode, CompletingChildNode: TCodeTreeNode;
|
||||
Tool: TFindDeclarationTool;
|
||||
Vis: TClassSectionVisibility;
|
||||
begin
|
||||
Result:=false;
|
||||
// search in new nodes, which will be inserted
|
||||
@ -566,9 +596,29 @@ begin
|
||||
exit(true);
|
||||
ANodeExt:=ANodeExt.Next;
|
||||
end;
|
||||
// ToDo: check ancestor vars too
|
||||
// search in current class
|
||||
Result:=(FindVarNode(FCompletingFirstEntryNode,UpperName)<>nil);
|
||||
if not Result then
|
||||
begin
|
||||
//search in ancestor classes
|
||||
Params:=TFindDeclarationParams.Create;
|
||||
try
|
||||
ClassNode:=CodeCompleteClassNode;
|
||||
Tool:=Self;
|
||||
while not Result and Tool.FindAncestorOfClass(ClassNode,Params,True) do begin
|
||||
Tool:=Params.NewCodeTool;
|
||||
ClassNode:=Params.NewNode;
|
||||
CompletingChildNode:=GetFirstClassIdentifier(ClassNode);
|
||||
if Tool=Self then
|
||||
Vis := csvPrivateAndHigher
|
||||
else
|
||||
Vis := csvProtectedAndHigher;
|
||||
Result := (Tool.FindVarNode(CompletingChildNode,UpperName,Vis)<>nil);
|
||||
end;
|
||||
finally
|
||||
Params.Free;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCodeCompletionCodeTool.AddClassInsertion(
|
||||
|
@ -66,6 +66,12 @@ type
|
||||
Group: TPascalMethodGroup;
|
||||
end;
|
||||
|
||||
TClassSectionVisibility = (
|
||||
csvEverything,//same class same unit
|
||||
csvPrivateAndHigher,//same unit different class
|
||||
csvProtectedAndHigher,//ancestor class different unit
|
||||
csvPublicAndHigher);//other class other unit
|
||||
|
||||
TOnEachPRIdentifier = procedure(Sender: TPascalParserTool;
|
||||
IdentifierCleanPos: integer; Range: TEPRIRange;
|
||||
Node: TCodeTreeNode; Data: Pointer; var Abort: boolean) of object;
|
||||
@ -141,9 +147,9 @@ type
|
||||
function GetProcNameIdentifier(ProcNode: TCodeTreeNode): PChar;
|
||||
function FindProcNode(StartNode: TCodeTreeNode; const AProcHead: string;
|
||||
AProcSpecType: TPascalMethodGroup;
|
||||
Attr: TProcHeadAttributes): TCodeTreeNode; overload;
|
||||
Attr: TProcHeadAttributes; Visibility: TClassSectionVisibility = csvEverything): TCodeTreeNode; overload;
|
||||
function FindProcNode(StartNode: TCodeTreeNode; const AProcHead: TPascalMethodHeader;
|
||||
Attr: TProcHeadAttributes): TCodeTreeNode; overload;
|
||||
Attr: TProcHeadAttributes; Visibility: TClassSectionVisibility = csvEverything): TCodeTreeNode; overload;
|
||||
function FindCorrespondingProcNode(ProcNode: TCodeTreeNode;
|
||||
Attr: TProcHeadAttributes = [phpWithoutClassKeyword,phpWithoutClassName]
|
||||
): TCodeTreeNode;
|
||||
@ -216,13 +222,15 @@ type
|
||||
function IsClassNode(Node: TCodeTreeNode): boolean; // class, not object
|
||||
function FindInheritanceNode(ClassNode: TCodeTreeNode): TCodeTreeNode;
|
||||
function FindHelperForNode(HelperNode: TCodeTreeNode): TCodeTreeNode;
|
||||
function IdentNodeIsInVisibleClassSection(Node: TCodeTreeNode; Visibility: TClassSectionVisibility): Boolean;
|
||||
|
||||
// records
|
||||
function ExtractRecordCaseType(RecordCaseNode: TCodeTreeNode): string;
|
||||
|
||||
// variables, types
|
||||
function FindVarNode(StartNode: TCodeTreeNode;
|
||||
const UpperVarName: string): TCodeTreeNode;
|
||||
const UpperVarName: string;
|
||||
Visibility: TClassSectionVisibility = csvEverything): TCodeTreeNode;
|
||||
function FindTypeNodeOfDefinition(
|
||||
DefinitionNode: TCodeTreeNode): TCodeTreeNode;
|
||||
function NodeIsPartOfTypeDefinition(ANode: TCodeTreeNode): boolean;
|
||||
@ -911,7 +919,8 @@ begin
|
||||
end;
|
||||
|
||||
function TPascalReaderTool.FindProcNode(StartNode: TCodeTreeNode;
|
||||
const AProcHead: TPascalMethodHeader; Attr: TProcHeadAttributes): TCodeTreeNode;
|
||||
const AProcHead: TPascalMethodHeader; Attr: TProcHeadAttributes;
|
||||
Visibility: TClassSectionVisibility): TCodeTreeNode;
|
||||
// search in all next brothers for a Procedure Node with the Name ProcName
|
||||
// if there are no further brothers and the parent is a section node
|
||||
// ( e.g. 'interface', 'implementation', ...) or a class visibility node
|
||||
@ -928,7 +937,9 @@ begin
|
||||
if (not ((phpIgnoreForwards in Attr)
|
||||
and ((Result.SubDesc and ctnsForwardDeclaration)>0)))
|
||||
and (not ((phpIgnoreProcsWithBody in Attr)
|
||||
and (FindProcBody(Result)<>nil))) then
|
||||
and (FindProcBody(Result)<>nil)))
|
||||
and (not InClass or IdentNodeIsInVisibleClassSection(Result, Visibility))
|
||||
then
|
||||
begin
|
||||
CurProcHead:=ExtractProcHeadWithGroup(Result,Attr);
|
||||
//DebugLn(['TPascalReaderTool.FindProcNode B "',CurProcHead,'" =? "',AProcHead,'" Result=',CompareTextIgnoringSpace(CurProcHead,AProcHead,false)]);
|
||||
@ -948,13 +959,13 @@ end;
|
||||
|
||||
function TPascalReaderTool.FindProcNode(StartNode: TCodeTreeNode;
|
||||
const AProcHead: string; AProcSpecType: TPascalMethodGroup;
|
||||
Attr: TProcHeadAttributes): TCodeTreeNode;
|
||||
Attr: TProcHeadAttributes; Visibility: TClassSectionVisibility): TCodeTreeNode;
|
||||
var
|
||||
ProcHead: TPascalMethodHeader;
|
||||
begin
|
||||
ProcHead.Name := AProcHead;
|
||||
ProcHead.Group := AProcSpecType;
|
||||
Result := FindProcNode(StartNode, ProcHead, Attr);
|
||||
Result := FindProcNode(StartNode, ProcHead, Attr, Visibility);
|
||||
end;
|
||||
|
||||
function TPascalReaderTool.FindCorrespondingProcNode(ProcNode: TCodeTreeNode;
|
||||
@ -2070,7 +2081,8 @@ begin
|
||||
end;
|
||||
|
||||
function TPascalReaderTool.FindVarNode(StartNode: TCodeTreeNode;
|
||||
const UpperVarName: string): TCodeTreeNode;
|
||||
const UpperVarName: string; Visibility: TClassSectionVisibility
|
||||
): TCodeTreeNode;
|
||||
var
|
||||
InClass: Boolean;
|
||||
begin
|
||||
@ -2078,6 +2090,7 @@ begin
|
||||
InClass:=FindClassOrInterfaceNode(StartNode)<>nil;
|
||||
while Result<>nil do begin
|
||||
if (Result.Desc=ctnVarDefinition)
|
||||
and (not InClass or IdentNodeIsInVisibleClassSection(Result, Visibility))
|
||||
and (CompareNodeIdentChars(Result,UpperVarName)=0) then
|
||||
exit;
|
||||
if InClass then
|
||||
@ -2487,6 +2500,26 @@ begin
|
||||
Result:=ctnNone;
|
||||
end;
|
||||
|
||||
function TPascalReaderTool.IdentNodeIsInVisibleClassSection(
|
||||
Node: TCodeTreeNode; Visibility: TClassSectionVisibility): Boolean;
|
||||
begin
|
||||
if Visibility = csvEverything then
|
||||
Result := True
|
||||
else
|
||||
if (Node.Parent<>nil) then
|
||||
case Visibility of
|
||||
//csvAbovePrivate: todo: add strict private and strict protected (should be registered as new sections)
|
||||
csvProtectedAndHigher:
|
||||
Result := not(Node.Parent.Desc = ctnClassPrivate);//todo: add strict private
|
||||
csvPublicAndHigher:
|
||||
Result := not(Node.Parent.Desc in [ctnClassPrivate, ctnClassProtected]);//todo: strict private and strict protected
|
||||
else
|
||||
Result := True
|
||||
end
|
||||
else
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
function TPascalReaderTool.ExtractProcedureGroup(ProcNode: TCodeTreeNode
|
||||
): TPascalMethodGroup;
|
||||
begin
|
||||
|
Loading…
Reference in New Issue
Block a user