mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-11-04 06:39:31 +01:00 
			
		
		
		
	codetools: added compiler procedure length to identifier completion
git-svn-id: trunk@9582 -
This commit is contained in:
		
							parent
							
								
									619b2afae0
								
							
						
					
					
						commit
						e28e38295b
					
				@ -212,6 +212,8 @@ type
 | 
			
		||||
    function ConsistencyCheck: integer; // 0 = ok
 | 
			
		||||
  end;
 | 
			
		||||
 | 
			
		||||
  { TCodeTree }
 | 
			
		||||
 | 
			
		||||
  TCodeTree = class
 | 
			
		||||
  private
 | 
			
		||||
    FNodeCount: integer;
 | 
			
		||||
@ -221,6 +223,7 @@ type
 | 
			
		||||
    procedure DeleteNode(ANode: TCodeTreeNode);
 | 
			
		||||
    procedure AddNodeAsLastChild(ParentNode, ANode: TCodeTreeNode);
 | 
			
		||||
    function FindLastPosition: integer;
 | 
			
		||||
    function ContainsNode(ANode: TCodeTreeNode): boolean;
 | 
			
		||||
    procedure Clear;
 | 
			
		||||
    constructor Create;
 | 
			
		||||
    destructor Destroy; override;
 | 
			
		||||
@ -678,6 +681,14 @@ begin
 | 
			
		||||
  Result:=ANode.EndPos;
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
function TCodeTree.ContainsNode(ANode: TCodeTreeNode): boolean;
 | 
			
		||||
begin
 | 
			
		||||
  if ANode=nil then exit(false);
 | 
			
		||||
  while ANode.Parent<>nil do ANode:=ANode.Parent;
 | 
			
		||||
  while ANode.PriorBrother<>nil do ANode:=ANode.PriorBrother;
 | 
			
		||||
  Result:=ANode=Root;
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
function TCodeTree.ConsistencyCheck: integer;
 | 
			
		||||
// 0 = ok
 | 
			
		||||
var RealNodeCount: integer;
 | 
			
		||||
 | 
			
		||||
@ -82,14 +82,14 @@ type
 | 
			
		||||
        Identifier+Range -> Source Position
 | 
			
		||||
      and can be interpreted as:
 | 
			
		||||
      Identifier is a PChar to the beginning of an identifier string.
 | 
			
		||||
      Range is a clenaed source range (CleanStartPos-CleanEndPos).
 | 
			
		||||
      Range is a cleaned source range (CleanStartPos-CleanEndPos).
 | 
			
		||||
      Source position is a tuple of NewTool, NewNode, NewCleanPos.
 | 
			
		||||
      If the current context node is a child of a caching node and it is in the
 | 
			
		||||
      range, then the result is valid. If NewNode=nil then there is no such
 | 
			
		||||
      identifier valid at the context node.
 | 
			
		||||
 | 
			
		||||
      Every node that define local identifiers contains a node cache.
 | 
			
		||||
      These are: class, proc, record, withstatement
 | 
			
		||||
      Every node that defines local identifiers contains a node cache.
 | 
			
		||||
      These are: class, interface, proc, record, withstatement
 | 
			
		||||
      
 | 
			
		||||
      Because node caches can store information of used units, the cache must be
 | 
			
		||||
      deleted every time a used unit is changed. Currently all node caches are
 | 
			
		||||
@ -647,7 +647,7 @@ var
 | 
			
		||||
  OldEntry: PCodeTreeNodeCacheEntry;
 | 
			
		||||
  OldNode: TAVLTreeNode;
 | 
			
		||||
  NewSearchRangeFlags: TNodeCacheEntryFlags;
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  function ParamsDebugReport: string;
 | 
			
		||||
  var
 | 
			
		||||
    s: string;
 | 
			
		||||
@ -704,8 +704,16 @@ var
 | 
			
		||||
 | 
			
		||||
begin
 | 
			
		||||
  OldEntry:=nil;
 | 
			
		||||
  // consistency checks
 | 
			
		||||
  if CleanStartPos>=CleanEndPos then
 | 
			
		||||
    RaiseConflictException('CleanStartPos>=CleanEndPos');
 | 
			
		||||
  if (NewNode<>nil) then begin
 | 
			
		||||
    if NewTool=nil then
 | 
			
		||||
      RaiseConflictException('NewNode<>nil and NewTool=nil');
 | 
			
		||||
    if not NewTool.Tree.ContainsNode(NewNode) then
 | 
			
		||||
      RaiseConflictException('NewNode is not a node of NewTool');
 | 
			
		||||
  end;
 | 
			
		||||
  
 | 
			
		||||
  {if GetIdentifier(Identifier)='TDefineAction' then begin
 | 
			
		||||
    DebugLn('[[[[======================================================');
 | 
			
		||||
    DebugLn('[TCodeTreeNodeCache.Add] Ident=',GetIdentifier(Identifier),
 | 
			
		||||
 | 
			
		||||
@ -74,7 +74,10 @@ type
 | 
			
		||||
  
 | 
			
		||||
  TIdentListItemFlag = (
 | 
			
		||||
    iliHasChilds,
 | 
			
		||||
    iliBaseExprTypeValid
 | 
			
		||||
    iliBaseExprTypeValid,
 | 
			
		||||
    iliIsFunction,
 | 
			
		||||
    iliIsFunctionValid,
 | 
			
		||||
    iliParamListValid
 | 
			
		||||
    );
 | 
			
		||||
  TIdentListItemFlags = set of TIdentListItemFlag;
 | 
			
		||||
  
 | 
			
		||||
@ -84,7 +87,6 @@ type
 | 
			
		||||
  private
 | 
			
		||||
    FNext: TIdentifierListItem;
 | 
			
		||||
    FParamList: string;
 | 
			
		||||
    FParamListValid: boolean;
 | 
			
		||||
    function GetParamList: string;
 | 
			
		||||
    procedure SetParamList(const AValue: string);
 | 
			
		||||
  public
 | 
			
		||||
@ -110,6 +112,7 @@ type
 | 
			
		||||
    function CanBeAssigned: boolean;
 | 
			
		||||
    procedure UpdateBaseContext;
 | 
			
		||||
    function HasChilds: boolean;
 | 
			
		||||
    function IsFunction: boolean;
 | 
			
		||||
    procedure Clear;
 | 
			
		||||
    function CompareParamList(CompareItem: TIdentifierListItem): integer;
 | 
			
		||||
  public
 | 
			
		||||
@ -276,8 +279,8 @@ type
 | 
			
		||||
                                   Node: TCodeTreeNode);
 | 
			
		||||
  public
 | 
			
		||||
    function GatherIdentifiers(const CursorPos: TCodeXYPosition;
 | 
			
		||||
      var IdentifierList: TIdentifierList;
 | 
			
		||||
      BeautifyCodeOptions: TBeautifyCodeOptions): boolean;
 | 
			
		||||
                            var IdentifierList: TIdentifierList;
 | 
			
		||||
                            BeautifyCodeOptions: TBeautifyCodeOptions): boolean;
 | 
			
		||||
    function FindCodeContext(const CursorPos: TCodeXYPosition;
 | 
			
		||||
                             out CodeContexts: TCodeContextInfo): boolean;
 | 
			
		||||
  end;
 | 
			
		||||
@ -854,86 +857,58 @@ const
 | 
			
		||||
    if ANode=nil then Result:=0;
 | 
			
		||||
  end;
 | 
			
		||||
  
 | 
			
		||||
  procedure AddCompilerProcedure(const AProcName, AParameterList: PChar);
 | 
			
		||||
  var
 | 
			
		||||
    NewItem: TIdentifierListItem;
 | 
			
		||||
  begin
 | 
			
		||||
    NewItem:=TIdentifierListItem.Create(
 | 
			
		||||
        icompUnknown,
 | 
			
		||||
        false,
 | 
			
		||||
        CompilerFuncHistoryIndex,
 | 
			
		||||
        AProcName,
 | 
			
		||||
        CompilerFuncLevel,
 | 
			
		||||
        nil,
 | 
			
		||||
        nil,
 | 
			
		||||
        ctnProcedure);
 | 
			
		||||
    NewItem.ParamList:=AParameterList;
 | 
			
		||||
    CurrentIdentifierList.Add(NewItem);
 | 
			
		||||
  end;
 | 
			
		||||
  
 | 
			
		||||
  procedure AddCompilerFunction(const AProcName, AParameterList,
 | 
			
		||||
    AResultType: PChar);
 | 
			
		||||
  var
 | 
			
		||||
    NewItem: TIdentifierListItem;
 | 
			
		||||
  begin
 | 
			
		||||
    NewItem:=TIdentifierListItem.Create(
 | 
			
		||||
        icompUnknown,
 | 
			
		||||
        false,
 | 
			
		||||
        CompilerFuncHistoryIndex,
 | 
			
		||||
        AProcName,
 | 
			
		||||
        CompilerFuncLevel,
 | 
			
		||||
        nil,
 | 
			
		||||
        nil,
 | 
			
		||||
        ctnProcedure);
 | 
			
		||||
    NewItem.ParamList:=AParameterList;
 | 
			
		||||
    NewItem.Flags:=NewItem.Flags+[iliIsFunction,iliIsFunctionValid];
 | 
			
		||||
    CurrentIdentifierList.Add(NewItem);
 | 
			
		||||
  end;
 | 
			
		||||
 | 
			
		||||
var
 | 
			
		||||
  NewItem: TIdentifierListItem;
 | 
			
		||||
  ProcNode: TCodeTreeNode;
 | 
			
		||||
begin
 | 
			
		||||
  if Context.Node.Desc in AllPascalStatements then begin
 | 
			
		||||
    // begin..end -> add 'SetLength'
 | 
			
		||||
    NewItem:=TIdentifierListItem.Create(
 | 
			
		||||
        icompUnknown,
 | 
			
		||||
        false,
 | 
			
		||||
        CompilerFuncHistoryIndex,
 | 
			
		||||
        'SetLength',
 | 
			
		||||
        CompilerFuncLevel,
 | 
			
		||||
        nil,
 | 
			
		||||
        nil,
 | 
			
		||||
        ctnProcedure);
 | 
			
		||||
    NewItem.ParamList:='array of type; NewLength: integer';
 | 
			
		||||
    CurrentIdentifierList.Add(NewItem);
 | 
			
		||||
 | 
			
		||||
    // begin..end -> add 'copy'
 | 
			
		||||
    NewItem:=TIdentifierListItem.Create(
 | 
			
		||||
        icompUnknown,
 | 
			
		||||
        false,
 | 
			
		||||
        CompilerFuncHistoryIndex,
 | 
			
		||||
        'Copy',
 | 
			
		||||
        CompilerFuncLevel,
 | 
			
		||||
        nil,
 | 
			
		||||
        nil,
 | 
			
		||||
        ctnProcedure);
 | 
			
		||||
    NewItem.ParamList:='const s: string; FromPosition, ToPosition: integer';
 | 
			
		||||
    CurrentIdentifierList.Add(NewItem);
 | 
			
		||||
 | 
			
		||||
    // begin..end -> add 'write'
 | 
			
		||||
    NewItem:=TIdentifierListItem.Create(
 | 
			
		||||
        icompUnknown,
 | 
			
		||||
        false,
 | 
			
		||||
        CompilerFuncHistoryIndex,
 | 
			
		||||
        'Write',
 | 
			
		||||
        CompilerFuncLevel,
 | 
			
		||||
        nil,
 | 
			
		||||
        nil,
 | 
			
		||||
        ctnProcedure);
 | 
			
		||||
    NewItem.ParamList:='Args : Arguments';
 | 
			
		||||
    CurrentIdentifierList.Add(NewItem);
 | 
			
		||||
 | 
			
		||||
    // begin..end -> add 'writeln'
 | 
			
		||||
    NewItem:=TIdentifierListItem.Create(
 | 
			
		||||
        icompUnknown,
 | 
			
		||||
        false,
 | 
			
		||||
        CompilerFuncHistoryIndex,
 | 
			
		||||
        'WriteLn',
 | 
			
		||||
        CompilerFuncLevel,
 | 
			
		||||
        nil,
 | 
			
		||||
        nil,
 | 
			
		||||
        ctnProcedure);
 | 
			
		||||
    NewItem.ParamList:='Args : Arguments';
 | 
			
		||||
    CurrentIdentifierList.Add(NewItem);
 | 
			
		||||
 | 
			
		||||
    // begin..end -> add 'read'
 | 
			
		||||
    NewItem:=TIdentifierListItem.Create(
 | 
			
		||||
        icompUnknown,
 | 
			
		||||
        false,
 | 
			
		||||
        CompilerFuncHistoryIndex,
 | 
			
		||||
        'Read',
 | 
			
		||||
        CompilerFuncLevel,
 | 
			
		||||
        nil,
 | 
			
		||||
        nil,
 | 
			
		||||
        ctnProcedure);
 | 
			
		||||
    CurrentIdentifierList.Add(NewItem);
 | 
			
		||||
 | 
			
		||||
    // begin..end -> add 'readln'
 | 
			
		||||
    NewItem:=TIdentifierListItem.Create(
 | 
			
		||||
        icompUnknown,
 | 
			
		||||
        false,
 | 
			
		||||
        CompilerFuncHistoryIndex,
 | 
			
		||||
        'ReadLn',
 | 
			
		||||
        CompilerFuncLevel,
 | 
			
		||||
        nil,
 | 
			
		||||
        nil,
 | 
			
		||||
        ctnProcedure);
 | 
			
		||||
    CurrentIdentifierList.Add(NewItem);
 | 
			
		||||
    AddCompilerProcedure('SetLength','array of type; NewLength: integer');
 | 
			
		||||
    AddCompilerProcedure('Copy','const s: string; FromPosition, ToPosition: integer');
 | 
			
		||||
    AddCompilerProcedure('Write','Args : Arguments');
 | 
			
		||||
    AddCompilerProcedure('WriteLn','Args : Arguments');
 | 
			
		||||
    AddCompilerProcedure('Read','');
 | 
			
		||||
    AddCompilerProcedure('ReadLn','');
 | 
			
		||||
    AddCompilerFunction('Length','array of type','ordinal');
 | 
			
		||||
    AddCompilerFunction('High','Argument','ordinal');
 | 
			
		||||
    AddCompilerFunction('Low','Argument','ordinal');
 | 
			
		||||
    AddCompilerProcedure('Include','set of enum; enum');
 | 
			
		||||
    AddCompilerProcedure('Exclude','set of enum; enum');
 | 
			
		||||
 | 
			
		||||
    if Context.Tool.NodeIsInAMethod(Context.Node)
 | 
			
		||||
    and (not CurrentIdentifierList.HasIdentifier('Self','')) then begin
 | 
			
		||||
@ -1411,7 +1386,6 @@ var
 | 
			
		||||
 | 
			
		||||
  function CheckContextIsParameter(var Ok: boolean): boolean;
 | 
			
		||||
  // returns true, on error or context is parameter
 | 
			
		||||
  // returns false, if no error and context is not parameter
 | 
			
		||||
  var
 | 
			
		||||
    VarNameAtom, ProcNameAtom: TAtomPosition;
 | 
			
		||||
    ParameterIndex: integer;
 | 
			
		||||
@ -1420,15 +1394,17 @@ var
 | 
			
		||||
    StartInSubContext: Boolean;
 | 
			
		||||
  begin
 | 
			
		||||
    Result:=false;
 | 
			
		||||
    // check if in a begin..end block
 | 
			
		||||
    if (CursorNode.Desc<>ctnBeginBlock)
 | 
			
		||||
    and (not CursorNode.HasParentOfType(ctnBeginBlock)) then exit;
 | 
			
		||||
    //DebugLn('CheckContextIsParameter ');
 | 
			
		||||
    // check is cursor is in a parameter list behind an identifier
 | 
			
		||||
    if not CheckParameterSyntax(CursorNode, CleanCursorPos,
 | 
			
		||||
      VarNameAtom, ProcNameAtom, ParameterIndex) then exit;
 | 
			
		||||
                                VarNameAtom, ProcNameAtom, ParameterIndex)
 | 
			
		||||
    then exit;
 | 
			
		||||
    if VarNameAtom.StartPos<1 then exit;
 | 
			
		||||
    //DebugLn('CheckContextIsParameter Variable=',GetAtom(VarNameAtom),' Proc=',GetAtom(ProcNameAtom),' ParameterIndex=',dbgs(ParameterIndex));
 | 
			
		||||
    
 | 
			
		||||
    // it is a parameter -> save ParameterIndex
 | 
			
		||||
    // it is a parameter -> create context
 | 
			
		||||
    Result:=true;
 | 
			
		||||
    if CurrentContexts=nil then
 | 
			
		||||
      CurrentContexts:=TCodeContextInfo.Create;
 | 
			
		||||
@ -1446,9 +1422,9 @@ var
 | 
			
		||||
      CurrentContexts.EndPos:=SrcLen+1;
 | 
			
		||||
 | 
			
		||||
    FindCollectionContext(Params,ProcNameAtom.StartPos,CursorNode,
 | 
			
		||||
      GatherContext,ContextExprStartPos,StartInSubContext);
 | 
			
		||||
                          GatherContext,ContextExprStartPos,StartInSubContext);
 | 
			
		||||
 | 
			
		||||
    // gather declarations of parameter lists
 | 
			
		||||
    // gather declarations of all parameter lists
 | 
			
		||||
    Params.ContextNode:=GatherContext.Node;
 | 
			
		||||
    Params.SetIdentifier(Self,@Src[ProcNameAtom.StartPos],@CollectAllContexts);
 | 
			
		||||
    Params.Flags:=[fdfSearchInAncestors,fdfCollect,fdfFindVariable];
 | 
			
		||||
@ -1515,7 +1491,7 @@ end;
 | 
			
		||||
 | 
			
		||||
function TIdentifierListItem.GetParamList: string;
 | 
			
		||||
begin
 | 
			
		||||
  if not FParamListValid then begin
 | 
			
		||||
  if not (iliParamListValid in Flags) then begin
 | 
			
		||||
    // Note: if you implement param lists for other than ctnProcedure, check
 | 
			
		||||
    //       CompareParamList
 | 
			
		||||
    if (Node<>nil) and (Node.Desc=ctnProcedure) then begin
 | 
			
		||||
@ -1525,7 +1501,7 @@ begin
 | 
			
		||||
      //debugln('TIdentifierListItem.GetParamList A ',GetIdentifier(Identifier),' ',Tool.MainFilename,' ',dbgs(Node.StartPos));
 | 
			
		||||
    end else
 | 
			
		||||
      FParamList:='';
 | 
			
		||||
    FParamListValid:=true;
 | 
			
		||||
    Include(Flags,iliParamListValid);
 | 
			
		||||
  end;
 | 
			
		||||
  Result:=FParamList;
 | 
			
		||||
end;
 | 
			
		||||
@ -1533,7 +1509,7 @@ end;
 | 
			
		||||
procedure TIdentifierListItem.SetParamList(const AValue: string);
 | 
			
		||||
begin
 | 
			
		||||
  FParamList:=AValue;
 | 
			
		||||
  FParamListValid:=true;
 | 
			
		||||
  Include(Flags,iliParamListValid);
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
function TIdentifierListItem.AsString: string;
 | 
			
		||||
@ -1641,10 +1617,20 @@ begin
 | 
			
		||||
  Result:=iliHasChilds in Flags;
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
function TIdentifierListItem.IsFunction: boolean;
 | 
			
		||||
begin
 | 
			
		||||
  if not (iliIsFunctionValid in Flags) then begin
 | 
			
		||||
    if (Node<>nil)
 | 
			
		||||
    and Tool.NodeIsFunction(Node) then
 | 
			
		||||
      Include(Flags,iliIsFunction);
 | 
			
		||||
    Include(Flags,iliIsFunctionValid);
 | 
			
		||||
  end;
 | 
			
		||||
  Result:=iliIsFunction in Flags;
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
procedure TIdentifierListItem.Clear;
 | 
			
		||||
begin
 | 
			
		||||
  FParamList:='';
 | 
			
		||||
  FParamListValid:=false;
 | 
			
		||||
  Compatibility:=icompUnknown;
 | 
			
		||||
  HistoryIndex:=0;
 | 
			
		||||
  Identifier:=nil;
 | 
			
		||||
 | 
			
		||||
@ -166,8 +166,7 @@ begin
 | 
			
		||||
      end;
 | 
			
		||||
      
 | 
			
		||||
    ctnProcedure:
 | 
			
		||||
      if (IdentItem.Node<>nil)
 | 
			
		||||
      and IdentItem.Tool.NodeIsFunction(IdentItem.Node) then begin
 | 
			
		||||
      if IdentItem.IsFunction then begin
 | 
			
		||||
        AColor:=clTeal;
 | 
			
		||||
        s:='function';
 | 
			
		||||
      end else begin
 | 
			
		||||
@ -210,13 +209,15 @@ begin
 | 
			
		||||
    ACanvas.Font.Style:=ACanvas.Font.Style+[fsBold];
 | 
			
		||||
    s:=GetIdentifier(IdentItem.Identifier);
 | 
			
		||||
    if MeasureOnly then
 | 
			
		||||
      Inc(Result.X, ACanvas.TextWidth(s))
 | 
			
		||||
    else
 | 
			
		||||
      Inc(Result.X, 1+ACanvas.TextWidth(s))
 | 
			
		||||
    else begin
 | 
			
		||||
      ACanvas.TextOut(x+1,y,s);
 | 
			
		||||
    inc(x,ACanvas.TextWidth(s));
 | 
			
		||||
    if x>MaxX then exit;
 | 
			
		||||
      inc(x,ACanvas.TextWidth(s));
 | 
			
		||||
      if x>MaxX then exit;
 | 
			
		||||
    end;
 | 
			
		||||
    ACanvas.Font.Style:=ACanvas.Font.Style-[fsBold];
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    s:='';
 | 
			
		||||
    if IdentItem.Node<>nil then begin
 | 
			
		||||
      case IdentItem.Node.Desc of
 | 
			
		||||
 | 
			
		||||
@ -259,20 +260,27 @@ begin
 | 
			
		||||
          s:=copy(s,1,50);
 | 
			
		||||
        end;
 | 
			
		||||
 | 
			
		||||
      else
 | 
			
		||||
        exit;
 | 
			
		||||
 | 
			
		||||
      end;
 | 
			
		||||
    end else begin
 | 
			
		||||
      // IdentItem.Node=nil
 | 
			
		||||
      exit;
 | 
			
		||||
      case IdentItem.GetDesc of
 | 
			
		||||
      ctnProcedure:
 | 
			
		||||
        begin
 | 
			
		||||
          s:=IdentItem.ParamList;
 | 
			
		||||
          if s<>'' then
 | 
			
		||||
            s:='('+s+')';
 | 
			
		||||
          s:=s+';'
 | 
			
		||||
        end;
 | 
			
		||||
      end;
 | 
			
		||||
    end;
 | 
			
		||||
    
 | 
			
		||||
    SetFontColor(clBlack);
 | 
			
		||||
    if MeasureOnly then
 | 
			
		||||
      Inc(Result.X, ACanvas.TextWidth(s))
 | 
			
		||||
    else
 | 
			
		||||
      ACanvas.TextOut(x+1,y,s);
 | 
			
		||||
    if s<>'' then begin
 | 
			
		||||
      SetFontColor(clBlack);
 | 
			
		||||
      if MeasureOnly then
 | 
			
		||||
        Inc(Result.X, ACanvas.TextWidth(s))
 | 
			
		||||
      else
 | 
			
		||||
        ACanvas.TextOut(x+1,y,s);
 | 
			
		||||
    end;
 | 
			
		||||
 | 
			
		||||
  end else begin
 | 
			
		||||
    // parse AKey for text and style
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user