diff --git a/components/codetools/codecompletiontool.pas b/components/codetools/codecompletiontool.pas index db4495602f..7e93bf265a 100644 --- a/components/codetools/codecompletiontool.pas +++ b/components/codetools/codecompletiontool.pas @@ -1883,9 +1883,8 @@ begin and (Src[VarNameAtom.StartPos]='@') then begin HasAtOperator:=true; inc(VarNameAtom.StartPos); - // ToDo: resolve pointer: @p to a PFindContext create p:TFindContext // ToDo: create event: @OnClick to a TNotifyEvent create a method - exit; + //debugln(['TCodeCompletionCodeTool.CompleteLocalVariableByParameter HasAtOperator ',GetAtom(VarNameAtom)]); end; if not IsValidIdent(GetAtom(VarNameAtom)) then exit; @@ -1934,7 +1933,6 @@ begin CleanPosToCodePos(VarNameAtom.StartPos,IgnorePos); IgnoreErrorAfter:=IgnorePos; try - debugln(['TCodeCompletionCodeTool.CompleteLocalVariableByParameter ToDo: check for overloads']); if not Context.Tool.FindIdentifierInContext(Params) then exit; finally ClearIgnoreErrorAfter; @@ -1947,7 +1945,7 @@ begin ParameterIndex); if (ParameterNode=nil) and (Params.NewNode.Desc in [ctnProperty,ctnProcedure]) then begin - DebugLn(' CompleteLocalVariableAsParameter Procedure does not have so many parameters'); + DebugLn([' CompleteLocalVariableAsParameter Procedure has less than ',ParameterIndex+1,' parameters']); exit; end; if ParameterNode<>nil then begin @@ -1969,17 +1967,47 @@ begin AliasType:=CleanFindContext; ExprType:=TypeTool.FindExpressionResultType(Params, TypeNode.StartPos,TypeNode.EndPos,@AliasType); - //debugln(['TCodeCompletionCodeTool.CompleteLocalVariableByParameter AliasType=',FindContextToString(AliasType)]); + //debugln(['TCodeCompletionCodeTool.CompleteLocalVariableByParameter parameter type: AliasType=',FindContextToString(AliasType)]); + + if HasAtOperator then begin + //debugln(['TCodeCompletionCodeTool.CompleteLocalVariableByParameter HasAtOperator ExprType=',ExprTypeToString(ExprType)]); + NewType:=''; + if (ExprType.Desc=xtContext) + and (ExprType.Context.Node<>nil) then begin + TypeNode:=ExprType.Context.Node; + TypeTool:=ExprType.Context.Tool; + if (TypeNode.Desc=ctnPointerType) then begin + // for example PMapID = ^... + if (TypeNode.FirstChild<>nil) + and (TypeNode.FirstChild.Desc=ctnIdentifier) then begin + // for example PMapID = ^TMapID + NewType:=TypeTool.ExtractCode(TypeNode.FirstChild.StartPos, + TypeNode.FirstChild.EndPos,[]); + debugln(['TCodeCompletionCodeTool.CompleteLocalVariableByParameter pointer to ',NewType]); + Params.Clear; + Params.ContextNode:=TypeNode; + Params.Flags:=fdfDefaultForExpressions; + AliasType:=CleanFindContext; + ExprType:=TypeTool.FindExpressionResultType(Params, + TypeNode.FirstChild.StartPos,TypeNode.FirstChild.EndPos, + @AliasType); + debugln(['TCodeCompletionCodeTool.CompleteLocalVariableByParameter parameter is pointer to type: AliasType=',FindContextToString(AliasType)]); + end; + end else begin + + end; + end; + if NewType='' then begin + debugln(['TCodeCompletionCodeTool.CompleteLocalVariableByParameter parameter has @ operator, but this is not implemented for ',ExprTypeToString(ExprType)]); + exit; + end; + end; if AliasType.Node<>nil then begin // an identifier MissingUnitName:=GetUnitNameForUsesSection(AliasType.Tool); //debugln(['TCodeCompletionCodeTool.CompleteLocalVariableByParameter MissingUnitName=',MissingUnitName]); end; - if HasAtOperator then begin - - end; - DebugLn('TCodeCompletionCodeTool.CompleteLocalVariableAsParameter NewType=',NewType); if NewType='' then RaiseException('CompleteLocalVariableAsParameter Internal error: NewType=""'); diff --git a/components/codetools/finddeclarationtool.pas b/components/codetools/finddeclarationtool.pas index 601df11641..1676b2d447 100644 --- a/components/codetools/finddeclarationtool.pas +++ b/components/codetools/finddeclarationtool.pas @@ -182,7 +182,7 @@ const fdfOnlyCompatibleProc, fdfSearchInAncestors, fdfCollect]; // initial flags for searches fdfDefaultForExpressions = [fdfSearchInParentNodes, fdfSearchInAncestors, - fdfExceptionOnNotFound]; + fdfExceptionOnNotFound,fdfIgnoreCurContextNode]; // for nicer output FindDeclarationFlagNames: array[TFindDeclarationFlag] of string = ( @@ -6324,7 +6324,7 @@ begin try TypeParams.ContextNode:=TypeNode; TypeParams.SetIdentifier(Self,nil,nil); - TypeParams.Flags:=fdfDefaultForExpressions+[fdfIgnoreCurContextNode]; + TypeParams.Flags:=fdfDefaultForExpressions; ExprType:=FindExpressionTypeOfTerm(TypeNode.StartPos,-1,TypeParams,false); //debugln(['TFindDeclarationTool.FindIdentifierInTypeOfConstant ExprType=',ExprTypeToString(ExprType)]); finally @@ -9009,10 +9009,12 @@ function TFindDeclarationTool.CheckParameterSyntax(CursorNode: TCodeTreeNode; ReadNextAtom; {$IFDEF VerboseCPS}DebugLn('CheckIdentifierAndParameterList Atom="',GetAtom,'"');{$ENDIF} if (CurPos.EndPos>CleanCursorPos) - or ((CurPos.EndPos=CleanCursorPos) and (CurPos.Flag=cafWord)) then begin + or ((CurPos.EndPos=CleanCursorPos) + and ((CurPos.Flag=cafWord) or AtomIsChar('@'))) + then begin // parameter found => search parameter expression bounds e.g. ', parameter ,' - // important: this function should work, even the code behind - // CleanCursorPos is buggy + // important: this function should work, even if the code + // behind CleanCursorPos has syntax errors {$IFDEF VerboseCPS}DebugLn('CheckIdentifierAndParameterList Parameter found, search range ...');{$ENDIF} ProcNameAtom:=CurProcNameAtom; ParameterIndex:=CurParameterIndex; @@ -9023,20 +9025,27 @@ function TFindDeclarationTool.CheckParameterSyntax(CursorNode: TCodeTreeNode; ReadNextAtom; {$IFDEF VerboseCPS}DebugLn('CheckIdentifierAndParameterList parameter atom "',GetAtom,'"');{$ENDIF} if (CurPos.Flag in [cafRoundBracketOpen,cafEdgedBracketOpen]) then - ReadTilBracketClose(false) + begin + // atom belongs to the parameter expression + if ParameterAtom.StartPos=ParameterAtom.EndPos then + ParameterAtom.StartPos:=CurPos.StartPos; + ReadTilBracketClose(false); + ParameterAtom.EndPos:=CurPos.EndPos; + end else - if (CurPos.Flag in [cafNone,cafComma,cafSemicolon,cafEnd, + if (CurPos.StartPos>SrcLen) + or (CurPos.Flag in [cafComma,cafSemicolon,cafEnd, cafRoundBracketClose,cafEdgedBracketClose]) or ((CurPos.Flag=cafWord) and (LastAtoms.GetValueAt(0).Flag=cafWord) and (not LastUpAtomIs(0,'INHERITED'))) then begin // end of parameter expression found - {$IFDEF VerboseCPS}DebugLn('CheckIdentifierAndParameterList end of parameter found');{$ENDIF} + {$IFDEF VerboseCPS}DebugLn('CheckIdentifierAndParameterList end of parameter found "',GetAtom,'" Parameter="',dbgstr(Src,ParameterAtom.StartPos,ParameterAtom.EndPos-ParameterAtom.StartPos),'"');{$ENDIF} exit(true); end else begin // atom belongs to the parameter expression - if ParameterAtom.StartPos=ParameterStart then + if ParameterAtom.StartPos=ParameterAtom.EndPos then ParameterAtom.StartPos:=CurPos.StartPos; ParameterAtom.EndPos:=CurPos.EndPos; end;