codetools: ctnReferencTo for typeinfo, code hints and type check

git-svn-id: trunk@54642 -
This commit is contained in:
mattias 2017-04-19 11:49:51 +00:00
parent d78b765eac
commit 5ad98a7bcf
8 changed files with 78 additions and 37 deletions

View File

@ -2059,7 +2059,8 @@ function TCodeCompletionCodeTool.CompleteEventAssignment(CleanCursorPos,
Params.Flags:=[fdfSearchInParentNodes,fdfSearchInAncestors,fdfSearchInHelpers]; Params.Flags:=[fdfSearchInParentNodes,fdfSearchInAncestors,fdfSearchInHelpers];
ProcContext:=PropVarContext.Tool.FindBaseTypeOfNode( ProcContext:=PropVarContext.Tool.FindBaseTypeOfNode(
Params,PropVarContext.Node); Params,PropVarContext.Node);
if (ProcContext.Node=nil) or (ProcContext.Node.Desc<>ctnProcedureType) if (ProcContext.Node=nil)
or not (ProcContext.Node.Desc in AllProcTypes)
then begin then begin
{$IFDEF CTDEBUG} {$IFDEF CTDEBUG}
DebugLn('FindEventTypeAtCursor not a procedure type'); DebugLn('FindEventTypeAtCursor not a procedure type');
@ -2591,7 +2592,7 @@ begin
TypeNode:=ExprType.Context.Node; TypeNode:=ExprType.Context.Node;
if HasAtOperator if HasAtOperator
or ((Scanner.CompilerMode=cmDelphi) and (ExprType.Desc=xtContext) // procedures in delphi mode without @ or ((Scanner.CompilerMode=cmDelphi) and (ExprType.Desc=xtContext) // procedures in delphi mode without @
and (TypeNode<>nil) and (TypeNode.Desc=ctnProcedureType)) then and (TypeNode<>nil) and (TypeNode.Desc in AllProcTypes)) then
begin begin
debugln(['TCodeCompletionCodeTool.CompleteLocalIdentifierByParameter HasAtOperator ExprType=',ExprTypeToString(ExprType)]); debugln(['TCodeCompletionCodeTool.CompleteLocalIdentifierByParameter HasAtOperator ExprType=',ExprTypeToString(ExprType)]);
NewType:=''; NewType:='';
@ -2617,7 +2618,7 @@ begin
@AliasType); @AliasType);
//debugln(['TCodeCompletionCodeTool.CompleteLocalIdentifierByParameter parameter is pointer to type: AliasType=',FindContextToString(AliasType)]); //debugln(['TCodeCompletionCodeTool.CompleteLocalIdentifierByParameter parameter is pointer to type: AliasType=',FindContextToString(AliasType)]);
end; end;
end else if TypeNode.Desc=ctnProcedureType then begin end else if TypeNode.Desc in AllProcTypes then begin
// for example TNotifyEvent = procedure(... // for example TNotifyEvent = procedure(...
if TypeTool.ProcNodeHasOfObject(TypeNode) then begin if TypeTool.ProcNodeHasOfObject(TypeNode) then begin
AddMethod(Identifier,TypeTool,TypeNode); AddMethod(Identifier,TypeTool,TypeNode);
@ -6379,7 +6380,7 @@ begin
AddAssignment('nil'); AddAssignment('nil');
ctnPointerType: ctnPointerType:
AddAssignment('nil'); AddAssignment('nil');
ctnProcedureType: ctnProcedureType,ctnReferenceTo:
// address of proc // address of proc
AddAssignment('nil'); AddAssignment('nil');
ctnProcedureHead: ctnProcedureHead:

View File

@ -147,7 +147,7 @@ const
ctnGenericParams = 94; // parent = ctnGenericType, children = ctnGenericParameter ctnGenericParams = 94; // parent = ctnGenericType, children = ctnGenericParameter
ctnGenericParameter = 95; // can has a child ctnGenericConstraint ctnGenericParameter = 95; // can has a child ctnGenericConstraint
ctnGenericConstraint = 96; // parent = ctnGenericParameter ctnGenericConstraint = 96; // parent = ctnGenericParameter
ctnReferenceTo = 97; // 1st child = ctnProcedure ctnReferenceTo = 97; // 1st child = ctnProcedureType
ctnConstant = 98; ctnConstant = 98;
ctnHintModifier = 99; // deprecated, platform, unimplemented, library, experimental ctnHintModifier = 99; // deprecated, platform, unimplemented, library, experimental
@ -192,9 +192,11 @@ const
[ctnGenericType,ctnSpecialize, [ctnGenericType,ctnSpecialize,
ctnIdentifier,ctnOpenArrayType,ctnRangedArrayType, ctnIdentifier,ctnOpenArrayType,ctnRangedArrayType,
ctnRecordCase,ctnRecordVariant, ctnRecordCase,ctnRecordVariant,
ctnProcedureType,ctnSetType,ctnRangeType,ctnEnumerationType, ctnProcedureType,ctnReferenceTo,
ctnSetType,ctnRangeType,ctnEnumerationType,
ctnEnumIdentifier,ctnLabel,ctnTypeType,ctnFileType,ctnPointerType, ctnEnumIdentifier,ctnLabel,ctnTypeType,ctnFileType,ctnPointerType,
ctnClassOfType,ctnVariantType,ctnConstant]; ctnClassOfType,ctnVariantType,ctnConstant];
AllProcTypes = [ctnProcedureType,ctnReferenceTo];
AllPascalStatements = [ctnBeginBlock,ctnWithStatement,ctnWithVariable, AllPascalStatements = [ctnBeginBlock,ctnWithStatement,ctnWithVariable,
ctnOnBlock,ctnOnIdentifier,ctnOnStatement, ctnOnBlock,ctnOnIdentifier,ctnOnStatement,
ctnInitialization,ctnFinalization]; ctnInitialization,ctnFinalization];
@ -266,7 +268,7 @@ type
function HasParentOfType(ParentDesc: TCodeTreeNodeDesc): boolean; function HasParentOfType(ParentDesc: TCodeTreeNodeDesc): boolean;
function HasAsRoot(RootNode: TCodeTreeNode): boolean; function HasAsRoot(RootNode: TCodeTreeNode): boolean;
function GetNodeOfType(ADesc: TCodeTreeNodeDesc): TCodeTreeNode; function GetNodeOfType(ADesc: TCodeTreeNodeDesc): TCodeTreeNode;
function GetNodeOfTypes(Descriptors: array of TCodeTreeNodeDesc): TCodeTreeNode; function GetNodeOfTypes(const Descriptors: array of TCodeTreeNodeDesc): TCodeTreeNode;
function GetTopMostNodeOfType(ADesc: TCodeTreeNodeDesc): TCodeTreeNode; function GetTopMostNodeOfType(ADesc: TCodeTreeNodeDesc): TCodeTreeNode;
function GetFindContextParent: TCodeTreeNode; function GetFindContextParent: TCodeTreeNode;
function GetLevel: integer; function GetLevel: integer;
@ -833,7 +835,7 @@ begin
Result:=Result.Parent; Result:=Result.Parent;
end; end;
function TCodeTreeNode.GetNodeOfTypes(Descriptors: array of TCodeTreeNodeDesc function TCodeTreeNode.GetNodeOfTypes(const Descriptors: array of TCodeTreeNodeDesc
): TCodeTreeNode; ): TCodeTreeNode;
var var
i: Integer; i: Integer;

View File

@ -583,7 +583,7 @@ begin
TypeContext.Tool.MoveCursorToNodeStart(TypeContext.Node); TypeContext.Tool.MoveCursorToNodeStart(TypeContext.Node);
TypeContext.Tool.RaiseException(ctsMethodTypeDefinitionNotFound); TypeContext.Tool.RaiseException(ctsMethodTypeDefinitionNotFound);
end; end;
if Result.Node.Desc<>ctnProcedureType then begin if not (Result.Node.Desc in AllProcTypes) then begin
TypeContext.Tool.MoveCursorToNodeStart(TypeContext.Node); TypeContext.Tool.MoveCursorToNodeStart(TypeContext.Node);
TypeContext.Tool.RaiseException(Format(ctsExpectedAMethodTypeButFound, [ TypeContext.Tool.RaiseException(Format(ctsExpectedAMethodTypeButFound, [
Result.Node.DescAsString])); Result.Node.DescAsString]));
@ -845,13 +845,18 @@ function TEventsCodeTool.CreateMethod(ClassNode: TCodeTreeNode;
Node: TCodeTreeNode; Node: TCodeTreeNode;
ParamNode: TCodeTreeNode; ParamNode: TCodeTreeNode;
begin begin
Node:=AFindContext.Node;
MethodUnitName:=AFindContext.Tool.GetSourceName(false); MethodUnitName:=AFindContext.Tool.GetSourceName(false);
AddNeededUnitToMainUsesSection(PChar(MethodUnitName)); AddNeededUnitToMainUsesSection(PChar(MethodUnitName));
// search every parameter type and collect units // search every parameter type and collect units
if not (AFindContext.Tool is TCodeCompletionCodeTool) then exit; if not (AFindContext.Tool is TCodeCompletionCodeTool) then exit;
if not (AFindContext.Node.Desc in [ctnProcedureType,ctnProcedure]) then exit; if Node.Desc=ctnReferenceTo then begin
ProcHeadNode:=AFindContext.Node.FirstChild; Node:=Node.FirstChild;
if Node=nil then exit;
end;
if not (Node.Desc in [ctnProcedureType,ctnProcedure]) then exit;
ProcHeadNode:=Node.FirstChild;
if (ProcHeadNode=nil) or (ProcHeadNode.Desc<>ctnProcedureHead) then exit; if (ProcHeadNode=nil) or (ProcHeadNode.Desc<>ctnProcedureHead) then exit;
if ProcHeadNode.FirstChild=nil then if ProcHeadNode.FirstChild=nil then
AFindContext.Tool.BuildSubTreeForProcHead(ProcHeadNode); AFindContext.Tool.BuildSubTreeForProcHead(ProcHeadNode);
@ -1166,7 +1171,7 @@ begin
exit; exit;
end else begin end else begin
if not FindTypeOfInstanceProperty(Instance,PropName,TypeContext,true) then exit; if not FindTypeOfInstanceProperty(Instance,PropName,TypeContext,true) then exit;
if TypeContext.Node.Desc<>ctnProcedureType then begin if not (TypeContext.Node.Desc in AllProcTypes) then begin
debugln(['TEventsCodeTool.CreateExprListFromPropertyInfo property '+DbgSName(Instance)+'.'+PropName+' is not method: ',TypeContext.Node.DescAsString]); debugln(['TEventsCodeTool.CreateExprListFromPropertyInfo property '+DbgSName(Instance)+'.'+PropName+' is not method: ',TypeContext.Node.DescAsString]);
exit; exit;
end; end;

View File

@ -10419,6 +10419,10 @@ begin
{$IFDEF CheckNodeTool}CheckNodeTool(Node);{$ENDIF} {$IFDEF CheckNodeTool}CheckNodeTool(Node);{$ENDIF}
Result:=Node; Result:=Node;
if Result=nil then exit; if Result=nil then exit;
if Result.Desc=ctnReferenceTo then begin
Result:=Result.FirstChild;
if Result=nil then exit;
end;
if (Result.Desc in [ctnProperty,ctnGlobalProperty]) then if (Result.Desc in [ctnProperty,ctnGlobalProperty]) then
Result:=Result.FirstChild Result:=Result.FirstChild
else if Result.Desc in [ctnProcedure,ctnProcedureHead,ctnProcedureType] then begin else if Result.Desc in [ctnProcedure,ctnProcedureHead,ctnProcedureType] then begin
@ -11433,6 +11437,10 @@ begin
{$IFDEF CheckNodeTool}CheckNodeTool(Node);{$ENDIF} {$IFDEF CheckNodeTool}CheckNodeTool(Node);{$ENDIF}
Result:=nil; Result:=nil;
if Node=nil then exit; if Node=nil then exit;
if Node.Desc=ctnReferenceTo then begin
Node:=Node.FirstChild;
if Node=nil then exit;
end;
if Node.Desc in [ctnProcedure,ctnProcedureType] then begin if Node.Desc in [ctnProcedure,ctnProcedureType] then begin
ProcNode:=Node; ProcNode:=Node;
//DebugLn(' FindNthParameterNode ProcNode="',copy(Params.NewCodeTool.Src,ProcNode.StartPos,ProcNode.EndPos-ProcNode.StartPos),'"'); //DebugLn(' FindNthParameterNode ProcNode="',copy(Params.NewCodeTool.Src,ProcNode.StartPos,ProcNode.EndPos-ProcNode.StartPos),'"');

View File

@ -2190,7 +2190,7 @@ begin
case FoundContext.Node.Desc of case FoundContext.Node.Desc of
ctnProcedure: ctnProcedure:
begin begin
//DebugLn('TIdentCompletionTool.CollectAllContexts CurrentContexts.ProcNameAtom.StartPos=',dbgs(CurrentIdentifierContexts.ProcNameAtom.StartPos)); //DebugLn('TIdentCompletionTool.CollectAllContexts Found Proc CurrentContexts.ProcNameAtom.StartPos=',dbgs(CurrentIdentifierContexts.ProcNameAtom.StartPos));
if (CurrentIdentifierContexts.ProcName='') then exit; if (CurrentIdentifierContexts.ProcName='') then exit;
FoundContext.Tool.MoveCursorToProcName(FoundContext.Node,true); FoundContext.Tool.MoveCursorToProcName(FoundContext.Node,true);
//DebugLn(['TIdentCompletionTool.CollectAllContexts ProcName=',GetIdentifier(@FoundContext.Tool.Src[FoundContext.Tool.CurPos.StartPos])]); //DebugLn(['TIdentCompletionTool.CollectAllContexts ProcName=',GetIdentifier(@FoundContext.Tool.Src[FoundContext.Tool.CurPos.StartPos])]);
@ -2201,7 +2201,7 @@ begin
// method without 'overload' hides inherited one // method without 'overload' hides inherited one
if not FoundContext.Tool.ProcNodeHasSpecifier(FoundContext.Node, psOVERLOAD) then if not FoundContext.Tool.ProcNodeHasSpecifier(FoundContext.Node, psOVERLOAD) then
Exclude(Params.Flags, fdfSearchInAncestors); Exclude(Params.Flags, fdfSearchInAncestors);
end else exit end else exit;
end; end;
ctnProperty,ctnGlobalProperty: ctnProperty,ctnGlobalProperty:
begin begin
@ -3156,7 +3156,8 @@ begin
if IdentEndPos=0 then ; if IdentEndPos=0 then ;
// find class and ancestors if existing (needed for protected identifiers) // find class and ancestors if existing (needed for protected identifiers)
FindContextClassAndAncestorsAndExtendedClassOfHelper(CursorPos,FICTClassAndAncestorsAndExtClassOfHelper); FindContextClassAndAncestorsAndExtendedClassOfHelper(CursorPos,
FICTClassAndAncestorsAndExtClassOfHelper);
if CursorNode<>nil then begin if CursorNode<>nil then begin
if not CheckContextIsParameter(Result) then begin if not CheckContextIsParameter(Result) then begin

View File

@ -4564,8 +4564,9 @@ function TPascalParserTool.KeyWordFuncTypeProc: boolean;
function(ParmList):SimpleType of object; function(ParmList):SimpleType of object;
procedure; cdecl; popstack; register; pascal; stdcall; procedure; cdecl; popstack; register; pascal; stdcall;
} }
var IsFunction, EqualFound: boolean; var IsFunction, EqualFound, IsReferenceTo: boolean;
begin begin
IsReferenceTo:=CurNode.Desc=ctnReferenceTo;
IsFunction:=UpAtomIs('FUNCTION'); IsFunction:=UpAtomIs('FUNCTION');
CreateChildNode; CreateChildNode;
CurNode.Desc:=ctnProcedureType; CurNode.Desc:=ctnProcedureType;
@ -4591,7 +4592,7 @@ begin
SaveRaiseCharExpectedButAtomFound(':'); SaveRaiseCharExpectedButAtomFound(':');
end; end;
end; end;
if UpAtomIs('OF') then begin if (not IsReferenceTo) and UpAtomIs('OF') then begin
if not ReadNextUpAtomIs('OBJECT') then if not ReadNextUpAtomIs('OBJECT') then
SaveRaiseStringExpectedButAtomFound('"object"'); SaveRaiseStringExpectedButAtomFound('"object"');
ReadNextAtom; ReadNextAtom;
@ -4616,14 +4617,16 @@ begin
UndoReadNextAtom; UndoReadNextAtom;
break; break;
end; end;
if UpAtomIs('IS') then begin if not IsReferenceTo then begin
ReadNextAtom; if UpAtomIs('IS') then begin
if not UpAtomIs('NESTED') then ReadNextAtom;
SaveRaiseStringExpectedButAtomFound('nested'); if not UpAtomIs('NESTED') then
end else if UpAtomIs('OF') then begin SaveRaiseStringExpectedButAtomFound('nested');
ReadNextAtom; end else if UpAtomIs('OF') then begin
if not UpAtomIs('OBJECT') then ReadNextAtom;
SaveRaiseStringExpectedButAtomFound('object'); if not UpAtomIs('OBJECT') then
SaveRaiseStringExpectedButAtomFound('object');
end;
end; end;
ReadNextAtom; ReadNextAtom;
if CurPos.Flag<>cafSemicolon then begin if CurPos.Flag<>cafSemicolon then begin
@ -5793,8 +5796,11 @@ var
ProcHeadNode: TCodeTreeNode; ProcHeadNode: TCodeTreeNode;
begin begin
if ProcNode.Desc=ctnProcedureHead then ProcNode:=ProcNode.Parent; if ProcNode.Desc=ctnProcedureHead then ProcNode:=ProcNode.Parent;
if ProcNode.Desc=ctnMethodMap then begin if ProcNode.Desc=ctnMethodMap then
exit; exit;
if ProcNode.Desc=ctnReferenceTo then begin
ProcNode:=ProcNode.FirstChild;
if ProcNode=nil then exit;
end; end;
if (not (ProcNode.Desc in [ctnProcedure,ctnProcedureType])) then begin if (not (ProcNode.Desc in [ctnProcedure,ctnProcedureType])) then begin
{$IFDEF CheckNodeTool} {$IFDEF CheckNodeTool}
@ -5871,10 +5877,6 @@ end;
procedure TPascalParserTool.BuildSubTreeForProcHead(ProcNode: TCodeTreeNode; procedure TPascalParserTool.BuildSubTreeForProcHead(ProcNode: TCodeTreeNode;
out FunctionResult: TCodeTreeNode); out FunctionResult: TCodeTreeNode);
begin begin
if ProcNode.Desc=ctnProcedureHead then
ProcNode:=ProcNode.Parent;
if not(ProcNode.Desc in [ctnProcedure,ctnProcedureType]) then
RaiseException('INTERNAL ERROR: TPascalParserTool.BuildSubTreeForProcHead with FunctionResult');
BuildSubTreeForProcHead(ProcNode); BuildSubTreeForProcHead(ProcNode);
FunctionResult:=ProcNode.FirstChild.FirstChild; FunctionResult:=ProcNode.FirstChild.FirstChild;
if (FunctionResult<>nil) and (FunctionResult.Desc=ctnParameterList) then if (FunctionResult<>nil) and (FunctionResult.Desc=ctnParameterList) then

View File

@ -1872,12 +1872,26 @@ begin
while IsHintModifier do ReadNextAtom; while IsHintModifier do ReadNextAtom;
end; end;
ctnProcedure,ctnProcedureType,ctnProcedureHead: ctnProcedureHead:
begin begin
if Node.Desc<>ctnProcedureHead then begin MoveCursorToFirstProcSpecifier(Node);
Node:=Node.FirstChild; // ToDo:
if Node=nil then exit; end;
end;
ctnProcedure,ctnProcedureType:
begin
Node:=Node.FirstChild;
if Node=nil then exit;
MoveCursorToFirstProcSpecifier(Node);
// ToDo:
end;
ctnReferenceTo:
begin
Node:=Node.FirstChild;
if (Node=nil) or (Node.Desc<>ctnProcedureType) then exit;
Node:=Node.FirstChild;
if Node=nil then exit;
MoveCursorToFirstProcSpecifier(Node); MoveCursorToFirstProcSpecifier(Node);
// ToDo: // ToDo:
end; end;
@ -3278,7 +3292,12 @@ begin
// ToDo: ppu, dcu // ToDo: ppu, dcu
Result:=false; Result:=false;
if (ProcNode=nil) or (ProcNode.Desc<>ctnProcedureType) then exit; if ProcNode=nil then exit;
if ProcNode.Desc=ctnReferenceTo then begin
ProcNode:=ProcNode.FirstChild;
if ProcNode=nil then exit;
end;
if ProcNode.Desc<>ctnProcedureType then exit;
MoveCursorToFirstProcSpecifier(ProcNode); MoveCursorToFirstProcSpecifier(ProcNode);
Result:=UpAtomIs('OF') and ReadNextUpAtomIs('OBJECT'); Result:=UpAtomIs('OF') and ReadNextUpAtomIs('OBJECT');
end; end;

View File

@ -388,10 +388,13 @@ procedure TCodeContextFrm.CreateHints(const CodeContexts: TCodeContextInfo);
try try
try try
Expr:=Tool.ConvertNodeToExpressionType(Node,Params); Expr:=Tool.ConvertNodeToExpressionType(Node,Params);
//debugln(['FindBaseType ',s,' ',ExprTypeToString(Expr)]);
if (Expr.Desc=xtContext) and (Expr.Context.Node<>nil) then begin if (Expr.Desc=xtContext) and (Expr.Context.Node<>nil) then begin
ExprTool:=Expr.Context.Tool; ExprTool:=Expr.Context.Tool;
ExprNode:=Expr.Context.Node; ExprNode:=Expr.Context.Node;
if ExprNode.Desc=ctnReferenceTo then begin
ExprNode:=ExprNode.FirstChild;
if ExprNode=nil then exit;
end;
case ExprNode.Desc of case ExprNode.Desc of
ctnProcedureType: ctnProcedureType:
begin begin