IDE: lazdoc: started simple hints

git-svn-id: trunk@12990 -
This commit is contained in:
mattias 2007-11-23 19:52:54 +00:00
parent b45bfc8cb3
commit 49f48b68dd
9 changed files with 273 additions and 160 deletions

View File

@ -41,7 +41,7 @@ type
TDeclarationInheritanceCacheItem = class
public
CodePos: TCodePosition;
ListOfPFindContext: TFPList;
ListOfPCodeXYPosition: TFPList;
destructor Destroy; override;
end;
@ -56,7 +56,7 @@ type
end;
TOnFindDeclarations = function(Code: TCodeBuffer; X,Y: integer;
out ListOfPFindContext: TFPList;
out ListOfPCodeXYPosition: TFPList;
Flags: TFindDeclarationListFlags): boolean of object;
TDeclarationInheritanceCache = class
@ -73,7 +73,7 @@ type
destructor Destroy; override;
procedure Clear;
function FindDeclarations(Code: TCodeBuffer; X,Y: integer;
out ListOfPFindContext: TFPList;
out ListOfPCodeXYPosition: TFPList;
out CacheWasUsed: boolean): boolean;
property OnFindDeclarations: TOnFindDeclarations read FOnFindDeclarations
write FOnFindDeclarations;
@ -165,7 +165,7 @@ begin
end;
function TDeclarationInheritanceCache.FindDeclarations(Code: TCodeBuffer; X,
Y: integer; out ListOfPFindContext: TFPList; out CacheWasUsed: boolean
Y: integer; out ListOfPCodeXYPosition: TFPList; out CacheWasUsed: boolean
): boolean;
var
CodePos: TCodePosition;
@ -173,7 +173,7 @@ var
Item: TDeclarationInheritanceCacheItem;
begin
Result:=false;
ListOfPFindContext:=nil;
ListOfPCodeXYPosition:=nil;
CacheWasUsed:=true;
if Code=nil then exit;
CodePos.Code:=Code;
@ -192,8 +192,8 @@ begin
AVLNode:=FCurrent.FindKey(@CodePos,@ComparePCodePosWithDeclInhCacheItem);
if AVLNode<>nil then begin
Item:=TDeclarationInheritanceCacheItem(AVLNode.Data);
ListOfPFindContext:=Item.ListOfPFindContext;
Result:=ListOfPFindContext<>nil;
ListOfPCodeXYPosition:=Item.ListOfPCodeXYPosition;
Result:=ListOfPCodeXYPosition<>nil;
exit;
end;
end;
@ -203,28 +203,35 @@ begin
DebugLn(['TDeclarationInheritanceCache.FindDeclarations searching ',Code.Filename,'(X=',X,',Y=',Y,')']);
// ask the codetools
if OnFindDeclarations(Code,X,Y,ListOfPFindContext,[])
and (ListOfPFindContext<>nil)
and (ListOfPFindContext.Count>0) then begin
if OnFindDeclarations(Code,X,Y,ListOfPCodeXYPosition,[])
and (ListOfPCodeXYPosition<>nil)
and (ListOfPCodeXYPosition.Count>0) then begin
Result:=true;
end else begin
FreeAndNil(ListOfPFindContext);
FreeAndNil(ListOfPCodeXYPosition);
Result:=false;
end;
// save to cache
Item:=TDeclarationInheritanceCacheItem.Create;
Item.CodePos:=CodePos;
Item.ListOfPFindContext:=ListOfPFindContext;
Item.ListOfPCodeXYPosition:=ListOfPCodeXYPosition;
CheckCurrentIsValid;
if FCurrent=nil then begin
FCurrent:=TDeclarationInheritanceCacheTree.CreateDeclInhTree;
OnGetNodesDeletedStep(FCurrent.CodeToolsChangeStep);
end;
FCurrent.Add(Item);
if ListOfPCodeXYPosition<>nil then
DebugLn(['TDeclarationInheritanceCache.FindDeclarations ',ListOfPCodeXYPositionToStr(ListOfPCodeXYPosition)]);
// clean up cache a bit
CleanCache(5);
// consistency check
AVLNode:=FCurrent.FindKey(@CodePos,@ComparePCodePosWithDeclInhCacheItem);
if Item<>TDeclarationInheritanceCacheItem(AVLNode.Data) then raise Exception.Create('');
end;
constructor TDeclarationInheritanceCacheTree.CreateDeclInhTree;
@ -242,8 +249,8 @@ end;
destructor TDeclarationInheritanceCacheItem.Destroy;
begin
FreeListOfPFindContext(ListOfPFindContext);
ListOfPFindContext:=nil;
FreeListOfPFindContext(ListOfPCodeXYPosition);
ListOfPCodeXYPosition:=nil;
inherited Destroy;
end;

View File

@ -366,9 +366,6 @@ type
function FindDeclarationAndOverload(Code: TCodeBuffer; X,Y: integer;
out ListOfPCodeXYPosition: TFPList;
Flags: TFindDeclarationListFlags): boolean;
function FindDeclarationNodeAndOverload(Code: TCodeBuffer; X,Y: integer;
out ListOfPFindContext: TFPList;
Flags: TFindDeclarationListFlags): boolean;
function FindMainDeclaration(Code: TCodeBuffer; X,Y: integer;
out NewCode: TCodeBuffer;
out NewX, NewY, NewTopLine: integer): boolean;
@ -1783,34 +1780,6 @@ begin
{$ENDIF}
end;
function TCodeToolManager.FindDeclarationNodeAndOverload(Code: TCodeBuffer; X,
Y: integer; out ListOfPFindContext: TFPList; Flags: TFindDeclarationListFlags
): boolean;
var
CursorPos: TCodeXYPosition;
begin
Result:=false;
{$IFDEF CTDEBUG}
DebugLn('TCodeToolManager.FindDeclarationNodeAndOverload A ',Code.Filename,' x=',dbgs(x),' y=',dbgs(y));
{$ENDIF}
if not InitCurCodeTool(Code) then exit;
CursorPos.X:=X;
CursorPos.Y:=Y;
CursorPos.Code:=Code;
{$IFDEF CTDEBUG}
DebugLn('TCodeToolManager.FindDeclarationNodeAndOverload B ',dbgs(FCurCodeTool.Scanner<>nil));
{$ENDIF}
try
Result:=FCurCodeTool.FindDeclarationNodeAndOverload(CursorPos,
ListOfPFindContext,Flags);
except
on e: Exception do Result:=HandleException(e);
end;
{$IFDEF CTDEBUG}
DebugLn('TCodeToolManager.FindDeclarationNodeAndOverload END ');
{$ENDIF}
end;
function TCodeToolManager.FindMainDeclaration(Code: TCodeBuffer; X, Y: integer;
out NewCode: TCodeBuffer; out NewX, NewY, NewTopLine: integer): boolean;
var

View File

@ -954,6 +954,7 @@ begin
inc(FFreeCount);
end else begin
// free list full -> free the ANode
ANode.Clear;// clear the node, so that dangling pointers can be spotted early
ANode.Free;
{$IFDEF DebugCTMemManager}
inc(FFreedCount);

View File

@ -321,6 +321,7 @@ type
function NodeSubDescToStr(Desc, SubDesc: integer): string;
function ConsistencyCheck: integer; virtual; // 0 = ok
procedure WriteDebugTreeReport;
procedure CheckNodeTool(Node: TCodeTreeNode);
constructor Create;
destructor Destroy; override;
end;
@ -563,6 +564,7 @@ function TCustomCodeTool.CompareNodeIdentChars(ANode: TCodeTreeNode;
const AnUpperIdent: string): integer;
var AnIdentLen, i, NodeSrcLen, MinLen, p: integer;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(ANode);{$ENDIF}
if (ANode.StartPos<=SrcLen) and (ANode.EndPos<=SrcLen+1)
and (ANode.StartPos>=1) then begin
AnIdentLen:=length(AnUpperIdent);
@ -1784,6 +1786,7 @@ end;
procedure TCustomCodeTool.MoveCursorToNodeStart(ANode: TCodeTreeNode);
begin
{$IFDEF CheckNodeTool}CheckNodeTool(ANode);{$ENDIF}
MoveCursorToCleanPos(ANode.StartPos);
CurNode:=ANode;
end;
@ -1932,6 +1935,7 @@ end;
procedure TCustomCodeTool.IncreaseTreeChangeStep(NodesDeleting: boolean);
begin
//DebugLn(['TCustomCodeTool.IncreaseTreeChangeStep ',DbgSName(Self),' NodesDeleting=',NodesDeleting]);
if FTreeChangeStep=High(integer) then
FTreeChangeStep:=Low(integer)
else
@ -2045,6 +2049,21 @@ begin
WriteSubTree(Tree.Root,' ');
end;
procedure TCustomCodeTool.CheckNodeTool(Node: TCodeTreeNode);
procedure RaiseForeignNode;
begin
RaiseCatchableException('TCustomCodeTool.CheckNodeTool '+DbgSName(Self)+' '+Node.DescAsString);
end;
begin
if Node=nil then exit;
while Node.Parent<>nil do Node:=Node.Parent;
while Node.PriorBrother<>nil do Node:=Node.PriorBrother;
if (Tree=nil) or (Tree.Root<>Node) then
RaiseForeignNode;
end;
function TCustomCodeTool.FindDeepestNodeAtPos(P: integer;
ExceptionOnNotFound: boolean): TCodeTreeNode;
begin
@ -2064,6 +2083,7 @@ var
ChildNode: TCodeTreeNode;
Brother: TCodeTreeNode;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(StartNode);{$ENDIF}
Result:=nil;
while StartNode<>nil do begin
//DebugLn('SearchInNode ',NodeDescriptionAsString(ANode.Desc),

View File

@ -732,9 +732,6 @@ type
function FindDeclarationAndOverload(const CursorPos: TCodeXYPosition;
out ListOfPCodeXYPosition: TFPList;
Flags: TFindDeclarationListFlags): boolean;
function FindDeclarationNodeAndOverload(const CursorPos: TCodeXYPosition;
out ListOfPFindContext: TFPList;
Flags: TFindDeclarationListFlags): boolean;
function FindClassAndAncestors(ClassNode: TCodeTreeNode;
out ListOfPFindContext: TFPList): boolean;
function FindContextClassAndAncestors(const CursorPos: TCodeXYPosition;
@ -1679,6 +1676,7 @@ begin
{$IFDEF ShowTriedContexts}
DebugLn('TFindDeclarationTool.FindDeclarationInUsesSection A');
{$ENDIF}
{$IFDEF CheckNodeTool}CheckNodeTool(UsesNode);{$ENDIF}
// reparse uses section
MoveCursorToNodeStart(UsesNode);
ReadNextAtom;
@ -1966,6 +1964,7 @@ var
FindContext: TFindContext;
Params: TFindDeclarationParams;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(ANode);{$ENDIF}
Result:=false;
if (ANode=nil) then exit;
ActivateGlobalWriteLock;
@ -2065,6 +2064,7 @@ var
Identifier: PChar;
Node: TCodeTreeNode;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(ContextNode);{$ENDIF}
// find declaration of identifier
Identifier:=@Src[IdentAtom.StartPos];
//DebugLn(['TFindDeclarationTool.IdentifierIsDefined ',GetIdentifier(Identifier),' ',CompareIdentifiers(Identifier,'Result'),' ',]);
@ -2932,6 +2932,7 @@ var
end;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(Node);{$ENDIF}
Result.Node:=Node;
Result.Tool:=Self;
Exclude(Params.Flags,fdfTopLvlResolving);
@ -3344,7 +3345,10 @@ begin
NewTool:=Self;
NewNode:=FindDeepestExpandedNodeAtPos(CleanPos,true);
NewPos:=CursorPos;
AddPos;
if (NewNode.Desc in AllIdentifierDefinitions)
and (PositionInDefinitionName(NewNode,CleanPos)) then begin
AddPos;
end;
CurCursorPos:=CursorPos;
CurTool:=Self;
@ -3377,90 +3381,6 @@ begin
end;
end;
function TFindDeclarationTool.FindDeclarationNodeAndOverload(
const CursorPos: TCodeXYPosition; out ListOfPFindContext: TFPList;
Flags: TFindDeclarationListFlags): boolean;
var
NewContext: TFindContext;
OldPositions: TFPList;
NodeList: TFPList;
procedure AddPos;
begin
AddFindContext(OldPositions,NewContext);
if (NodeList.IndexOf(NewContext.Node)>=0) then
exit;
NodeList.Add(NewContext.Node);
if (fdlfWithoutEmptyProperties in Flags)
and (NewContext.Node.Desc=ctnProperty)
and (NewContext.Tool.PropNodeIsTypeLess(NewContext.Node)) then
exit;
if (fdlfWithoutForwards in Flags) then begin
if (NewContext.Node.Desc in [ctnTypeDefinition,ctnGenericType])
and NewContext.Tool.NodeIsForwardDeclaration(NewContext.Node)
then
exit;
if (NewContext.Node.Desc=ctnProcedure)
and ((NewContext.Node.SubDesc and ctnsForwardDeclaration)>0) then
exit;
end;
AddFindContext(ListOfPFindContext,NewContext);
end;
var
CurCursorPos: TCodeXYPosition;
CurTool: TFindDeclarationTool;
NewPos: TCodeXYPosition;
NewTopLine: integer;
CleanPos: integer;
begin
Result:=true;
ListOfPFindContext:=nil;
NewContext:=CleanFindContext;
OldPositions:=nil;
NodeList:=nil;
ActivateGlobalWriteLock;
try
BuildTreeAndGetCleanPos(trAll,CursorPos,CleanPos,[]);
NodeList:=TFPList.Create;
NewContext.Tool:=Self;
NewContext.Node:=FindDeepestExpandedNodeAtPos(CleanPos,true);
AddPos;
CurCursorPos:=CursorPos;
CurTool:=Self;
try
while CurTool.FindDeclaration(CurCursorPos,AllFindSmartFlags
+[fsfSearchSourceName],
NewContext.Tool,NewContext.Node,NewPos,NewTopLine) do
begin
if IndexOfFindContext(OldPositions,@NewContext)>=0 then break;
AddPos;
CurCursorPos:=NewPos;
CurTool:=NewContext.Tool;
debugln('TFindDeclarationTool.FindDeclarationAndOverload ',
' Self="',MainFilename,'" ');
if CurCursorPos.Code<>nil then
debugln(' CurCursorPos=',CurCursorPos.Code.Filename,' ',dbgs(CurCursorPos.X),',',dbgs(CurCursorPos.Y));
if CurTool<>nil then
debugln(' CurTool=',CurTool.MainFilename);
if (CurTool=nil) then exit;
end;
except
// ignore normal errors
on E: ECodeToolError do ;
on E: ELinkScannerError do ;
end;
finally
FreeListOfPFindContext(OldPositions);
NodeList.Free;
DeactivateGlobalWriteLock;
end;
end;
function TFindDeclarationTool.FindClassAndAncestors(ClassNode: TCodeTreeNode;
out ListOfPFindContext: TFPList): boolean;
var
@ -3468,6 +3388,7 @@ var
CurTool: TFindDeclarationTool;
Params: TFindDeclarationParams;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(ClassNode);{$ENDIF}
Result:=true;
ListOfPFindContext:=nil;
if (ClassNode=nil) or (ClassNode.Desc<>ctnClass) or (ClassNode.Parent=nil)
@ -3921,6 +3842,7 @@ function TFindDeclarationTool.CleanPosIsDeclarationIdentifier(CleanPos: integer;
end;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(Node);{$ENDIF}
Result:=false;
if Node=nil then exit;
case Node.Desc of
@ -3970,6 +3892,7 @@ function TFindDeclarationTool.JumpToNode(ANode: TCodeTreeNode;
var
JumpPos: LongInt;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(ANode);{$ENDIF}
Result:=false;
if (ANode=nil) or (ANode.StartPos<1) then exit;
JumpPos:=ANode.StartPos;
@ -4050,6 +3973,7 @@ function TFindDeclarationTool.NodeIsForwardDeclaration(Node: TCodeTreeNode
var
TypeNode: TCodeTreeNode;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(Node);{$ENDIF}
Result:=false;
if (Node=nil) or (not (Node.Desc in [ctnTypeDefinition,ctnGenericType])) then
exit;
@ -4071,6 +3995,7 @@ function TFindDeclarationTool.FindIdentifierInProcContext(
var
NameAtom: TAtomPosition;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(ProcContextNode);{$ENDIF}
Result:=ifrProceedSearch;
// if proc is a method body, search in class
// -> find class name
@ -4107,6 +4032,7 @@ var
OldInput: TFindDeclarationInput;
ClassContext: TFindContext;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(ProcContextNode);{$ENDIF}
Result:=false;
// if proc is a method, search in class
// -> find class name
@ -4184,6 +4110,7 @@ var
ClassContext: TFindContext;
CurClassNode: TCodeTreeNode;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(ProcNode);{$ENDIF}
{$IFDEF ShowTriedContexts}
DebugLn('[TFindDeclarationTool.FindClassOfMethod] A ');
{$ENDIF}
@ -4254,6 +4181,7 @@ var AncestorAtom: TAtomPosition;
SearchBaseClass: boolean;
AncestorContext: TFindContext;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(ClassNode);{$ENDIF}
if (ClassNode=nil) or (not (ClassNode.Desc in [ctnClass,ctnClassInterface]))
then
RaiseException('[TFindDeclarationTool.FindAncestorOfClass] '
@ -4378,6 +4306,7 @@ begin
' WithStart=',StringToPascalConst(copy(Src,WithVarNode.StartPos,15))
);
{$ENDIF}
{$IFDEF CheckNodeTool}CheckNodeTool(WithVarNode);{$ENDIF}
Result:=false;
// find the base type of the with variable
// move cursor to start of with-variable
@ -4646,6 +4575,7 @@ var
NewCodeTool: TFindDeclarationTool;
OldFlags: TFindDeclarationFlags;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(UsesNode);{$ENDIF}
Result:=false;
MoveCursorToUsesEnd(UsesNode);
repeat
@ -4841,6 +4771,7 @@ end;
function TFindDeclarationTool.CompareNodeIdentifier(Node: TCodeTreeNode;
Params: TFindDeclarationParams): boolean;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(Node);{$ENDIF}
Result:=false;
if Node=nil then exit;
if Node.Desc in AllSourceTypes then begin
@ -5900,6 +5831,7 @@ var
BaseContext: TFindContext;
OldInput: TFindDeclarationInput;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(Node);{$ENDIF}
{$IFDEF ShowExprEval}
DebugLn('[TFindDeclarationTool.ConvertNodeToExpressionType] A',
' Node=',Node.DescAsString);
@ -6311,6 +6243,7 @@ var
ParamCompatibility: TTypeCompatibility;
CompatibilityListCount: LongInt;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(FirstTargetParameterNode);{$ENDIF}
// quick check: parameter count
ParamNode:=FirstTargetParameterNode;
MinParamCnt:=0;
@ -6404,8 +6337,9 @@ var
ParamCompatibility: TTypeCompatibility;
SourceExprType: TExpressionType;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(FirstSourceParameterNode);{$ENDIF}
// quick check: parameter count
MinParamCnt:=0;
ParamNode:=FirstSourceParameterNode;
while (ParamNode<>nil) do begin
@ -6477,6 +6411,7 @@ var
OldFlags: TFindDeclarationFlags;
i: integer;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(FirstTargetParameterNode);{$ENDIF}
// quick check: parameter count
CurParamNode1:=FirstTargetParameterNode;
CurParamNode2:=FirstSourceParameterNode;
@ -6518,6 +6453,7 @@ end;
function TFindDeclarationTool.GetParameterNode(Node: TCodeTreeNode
): TCodeTreeNode;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(Node);{$ENDIF}
Result:=Node;
if Result<>nil then begin
if (Result.Desc=ctnProperty) then
@ -6776,6 +6712,7 @@ function TFindDeclarationTool.DoOnIdentifierFound(
// this internal function is called, whenever an identifier is found
var IsTopLvlIdent: boolean;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(FoundNode);{$ENDIF}
IsTopLvlIdent:=(fdfTopLvlResolving in Params.Flags);
if Assigned(Params.OnIdentifierFound) then
Result:=Params.OnIdentifierFound(Params,CreateFindContext(Self,FoundNode))
@ -6793,6 +6730,7 @@ var TargetContext: TFindContext;
OldInput: TFindDeclarationInput;
NodeExprType: TExpressionType;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(TargetNode);{$ENDIF}
{$IFDEF ShowExprEval}
DebugLn('[TFindDeclarationTool.IsCompatible] A Node=',TargetNode.DescAsString,
' ExpressionType=',ExpressionTypeDescNames[ExpressionType.Desc]);
@ -6991,6 +6929,7 @@ var
ExprType: TExpressionType;
ParamNode: TCodeTreeNode;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(ProcNode);{$ENDIF}
{$IFDEF ShowExprEval}
DebugLn('[TFindDeclarationTool.CreateParamExprListFromProcNode] ',
'"',copy(Src,ProcNode.StartPos,40),'" Context=',ProcNode.DescAsString);
@ -7311,6 +7250,7 @@ function TFindDeclarationTool.CheckParameterSyntax(CursorNode: TCodeTreeNode;
end;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(CursorNode);{$ENDIF}
Result:=false;
//DebugLn('TFindDeclarationTool.CheckParameterSyntax START');
@ -7338,6 +7278,7 @@ var
ParameterNode: TCodeTreeNode;
i: Integer;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(Node);{$ENDIF}
Result:=nil;
if Node=nil then exit;
if Node.Desc in [ctnProcedure] then begin
@ -7622,6 +7563,7 @@ end;
function TFindDeclarationTool.GetNodeCache(Node: TCodeTreeNode;
CreateIfNotExists: boolean): TCodeTreeNodeCache;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(Node);{$ENDIF}
while (Node<>nil) and (not (Node.Desc in AllNodeCacheDescs)) do
Node:=Node.Parent;
if Node<>nil then begin
@ -7668,6 +7610,7 @@ var Node: TCodeTreeNode;
{$ENDIF}
begin
{$IFDEF CheckNodeTool}CheckNodeTool(StartNode);{$ENDIF}
if StartNode=nil then exit;
if Params.NewNode<>nil then begin
// identifier found
@ -7795,6 +7738,7 @@ end;
function TFindDeclarationTool.CreateNewNodeCache(
Node: TCodeTreeNode): TCodeTreeNodeCache;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(Node);{$ENDIF}
Result:=NodeCacheMemManager.NewNodeCache(Node);
Result.Next:=FFirstNodeCache;
FFirstNodeCache:=Result;
@ -7803,6 +7747,7 @@ end;
function TFindDeclarationTool.CreateNewBaseTypeCache(Node: TCodeTreeNode
): TBaseTypeCache;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(Node);{$ENDIF}
Result:=BaseTypeCacheMemManager.NewBaseTypeCache(Node);
Result.Next:=FFirstBaseTypeCache;
FFirstBaseTypeCache:=Result;
@ -7874,6 +7819,7 @@ var
FindContext: TFindContext;
ANode: TCodeTreeNode;
begin
{$IFDEF CheckNodeTool}CheckNodeTool(CursorNode);{$ENDIF}
Result:='';
Params.ContextNode:=CursorNode;
Params.Flags:=[fdfSearchInParentNodes,fdfSearchInAncestors,
@ -8153,6 +8099,7 @@ begin
ClearResult(true);
NewCodeTool:=ANewCodeTool;
NewNode:=ANewNode;
{$IFDEF CheckNodeTool}if NewCodeTool<>nil then NewCodeTool.CheckNodeTool(NewNode);{$ENDIF}
end;
procedure TFindDeclarationParams.SetResult(ANewCodeTool: TFindDeclarationTool;
@ -8162,6 +8109,7 @@ begin
NewCodeTool:=ANewCodeTool;
NewNode:=ANewNode;
NewCleanPos:=ANewCleanPos;
{$IFDEF CheckNodeTool}if NewCodeTool<>nil then NewCodeTool.CheckNodeTool(NewNode);{$ENDIF}
end;
procedure TFindDeclarationParams.ConvertResultCleanPosToCaretPos;

View File

@ -145,6 +145,8 @@ type
function NodeIsPartOfTypeDefinition(ANode: TCodeTreeNode): boolean;
function ExtractDefinitionNodeType(DefinitionNode: TCodeTreeNode): string;
function ExtractDefinitionName(DefinitionNode: TCodeTreeNode): string;
function PositionInDefinitionName(DefinitionNode: TCodeTreeNode;
CleanPos: integer): boolean;
function MoveCursorToParameterSpecifier(DefinitionNode: TCodeTreeNode
): boolean;
@ -1502,6 +1504,22 @@ begin
end;
end;
function TPascalReaderTool.PositionInDefinitionName(
DefinitionNode: TCodeTreeNode; CleanPos: integer): boolean;
var
StartPos: LongInt;
begin
if DefinitionNode.Desc=ctnGenericType then begin
if DefinitionNode.FirstChild<>nil then
StartPos:=DefinitionNode.FirstChild.StartPos
else
StartPos:=0;
end else begin
StartPos:=DefinitionNode.StartPos;
end;
Result:=(CleanPos>=StartPos) and (CleanPos<StartPos+GetIdentLen(@Src[StartPos]));
end;
function TPascalReaderTool.MoveCursorToParameterSpecifier(
DefinitionNode: TCodeTreeNode): boolean;
begin

View File

@ -33,13 +33,17 @@ unit HelpManager;
interface
uses
// FCL+LCL
Classes, SysUtils, LCLProc, Forms, Controls, Buttons, StdCtrls, Dialogs,
ExtCtrls, LResources, FileUtil,
// CodeTools
BasicCodeTools, CodeToolManager, CodeAtom, CodeCache, CustomCodeTool, CodeTree,
PascalParserTool, FindDeclarationTool,
// IDEIntf
PropEdits, ObjectInspector, FormEditingIntf, ProjectIntf,
LazHelpIntf, LazHelpHTML, HelpFPDoc, MacroIntf, IDEWindowIntf, IDEMsgIntf,
LazIDEIntf, HelpIntfs, IDEHelpIntf,
// IDE
LazarusIDEStrConsts, TransferMacros, DialogProcs, IDEOptionDefs,
ObjInspExt, EnvironmentOpts, AboutFrm, MsgView, Project, PackageDefs, MainBar,
OutputFilter, HelpOptions, MainIntf, LazConf, HelpFPCMessages, LazDoc,
@ -880,13 +884,21 @@ function THelpManager.GetHintForSourcePosition(const ExpandedFilename: string;
const CodePos: TPoint; out Hint: string): TShowHelpResult;
var
Code: TCodeBuffer;
{$IFDEF EnableLazDocHint}
CacheWasUsed: boolean;
{$ENDIF}
begin
Hint:='';
Code:=CodeToolBoss.LoadFile(ExpandedFilename,true,false);
if Code=nil then exit;
{$IFDEF EnableLazDocHint}
if LazDocBoss.GetHint(Code,CodePos.X,CodePos.Y,true,Hint,CacheWasUsed)=ldprSuccess
then
exit(shrSuccess);
{$ENDIF}
Hint:=CodeToolBoss.FindSmartHint(Code,CodePos.X,CodePos.Y);
CodeToolBoss.Abortable:=false;
Result:=shrSuccess;
end;
function THelpManager.ConvertSourcePosToPascalHelpContext(

View File

@ -39,6 +39,16 @@ uses
CompilerOptions, IDEProcs, PackageDefs, EnvironmentOpts;
type
TFPDocItem = (
fpdiShort,
fpdiDescription,
fpdiErrors,
fpdiSeeAlso,
fpdiExample
);
TFPDocNode = array [TFPDocItem] of String;
{ TLazFPDocFile }
TLazFPDocFile = class
@ -51,6 +61,8 @@ type
function GetModuleNode: TDOMNode;
function GetFirstElement: TDOMNode;
function GetElementWithName(const ElementName: string): TDOMNode;
function GetFirstChildValue(Node: TDOMNode): String;
function GetValuesFromNode(Node: TDOMNode): TFPDocNode;
end;
{ TLDSourceToFPDocFile - cache item for source to FPDoc file mapping }
@ -142,11 +154,14 @@ type
out FPDocFile: TLazFPDocFile; out DOMNode: TDOMNode;
out CacheWasUsed: boolean): TLazDocParseResult;
function GetDeclarationChain(Code: TCodeBuffer; X, Y: integer;
out ListOfPFindContext: TFPList;
out ListOfPCodeXYPosition: TFPList;
out CacheWasUsed: boolean): TLazDocParseResult;
function GetElementChain(Code: TCodeBuffer; X, Y: integer; Complete: boolean;
out Chain: TLazDocElementChain;
out CacheWasUsed: boolean): TLazDocParseResult;
function GetHint(Code: TCodeBuffer; X, Y: integer; Complete: boolean;
out Hint: string;
out CacheWasUsed: boolean): TLazDocParseResult;
public
// Event lists
procedure RemoveAllHandlersOfObject(AnObject: TObject);
@ -243,6 +258,45 @@ begin
end;
end;
function TLazFPDocFile.GetFirstChildValue(Node: TDOMNode): String;
begin
if Assigned(Node.FirstChild) then
Result := Node.FirstChild.NodeValue
else
Result := '';
end;
function TLazFPDocFile.GetValuesFromNode(Node: TDOMNode): TFPDocNode;
var
S: String;
begin
Node := Node.FirstChild;
while Assigned(Node) do
begin
if (Node.NodeType = ELEMENT_NODE) then
begin
S := Node.NodeName;
if S = 'short' then
Result[fpdiShort] := GetFirstChildValue(Node);
if S = 'descr' then
Result[fpdiDescription] := GetFirstChildValue(Node);
if S = 'errors' then
Result[fpdiErrors] := GetFirstChildValue(Node);
if S = 'seealso' then
Result[fpdiSeeAlso] := GetFirstChildValue(Node);
if S = 'example' then begin
Result[fpdiExample] := Node.Attributes.GetNamedItem('file').NodeValue;
end;
end;
Node := Node.NextSibling;
end;
end;
procedure TLazDocManager.AddHandler(HandlerType: TLazDocManagerHandler;
const AMethod: TMethod; AsLast: boolean);
begin
@ -272,7 +326,7 @@ begin
FDocs:=TAvgLvlTree.Create(@CompareLazFPDocFilenames);
FSrcToDocMap:=TAvgLvlTree.Create(@CompareLDSrc2DocSrcFilenames);
FDeclarationCache:=TDeclarationInheritanceCache.Create(
@CodeToolBoss.FindDeclarationNodeAndOverload,
@CodeToolBoss.FindDeclarationAndOverload,
@CodeToolBoss.GetCodeTreeNodesDeletedStep);
end;
@ -543,10 +597,10 @@ begin
end;
function TLazDocManager.GetDeclarationChain(Code: TCodeBuffer; X, Y: integer;
out ListOfPFindContext: TFPList; out CacheWasUsed: boolean
out ListOfPCodeXYPosition: TFPList; out CacheWasUsed: boolean
): TLazDocParseResult;
begin
if FDeclarationCache.FindDeclarations(Code,X,Y,ListOfPFindContext,
if FDeclarationCache.FindDeclarations(Code,X,Y,ListOfPCodeXYPosition,
CacheWasUsed)
then
Result:=ldprSuccess
@ -558,36 +612,75 @@ function TLazDocManager.GetElementChain(Code: TCodeBuffer; X, Y: integer;
Complete: boolean; out Chain: TLazDocElementChain; out CacheWasUsed: boolean
): TLazDocParseResult;
var
ListOfPFindContext: TFPList;
ListOfPCodeXYPosition: TFPList;
i: Integer;
CodeContext: PFindContext;
CodePos: PCodeXYPosition;
CurTool: TCodeTool;
CleanPos: integer;
LDElement: TLazDocElement;
SrcFilename: String;
FPDocFilename: String;
Node: TCodeTreeNode;
begin
Chain:=nil;
ListOfPFindContext:=nil;
ListOfPCodeXYPosition:=nil;
try
DebugLn(['TLazDocManager.GetElementChain GetDeclarationChain...']);
// get the declaration chain
Result:=GetDeclarationChain(Code,X,Y,ListOfPFindContext,CacheWasUsed);
Result:=GetDeclarationChain(Code,X,Y,ListOfPCodeXYPosition,CacheWasUsed);
if Result<>ldprSuccess then exit;
if (not CacheWasUsed) and (not Complete) then exit(ldprParsing);
DebugLn(['TLazDocManager.GetElementChain init the element chain: ListOfPFindContext.Count=',ListOfPFindContext.Count,' ...']);
DebugLn(['TLazDocManager.GetElementChain init the element chain: ListOfPCodeXYPosition.Count=',ListOfPCodeXYPosition.Count,' ...']);
// init the element chain
Result:=ldprParsing;
Chain:=TLazDocElementChain.Create;
Chain.CodePos.Code:=Code;
Code.LineColToPosition(Y,X,Chain.CodePos.P);
// fill the element chain
for i:=0 to ListOfPFindContext.Count-1 do begin
LDElement:=Chain.Add;
for i:=0 to ListOfPCodeXYPosition.Count-1 do begin
// get source position of declaration
CodeContext:=PFindContext(ListOfPFindContext[i]);
LDElement.CodeContext:=CodeContext^;
DebugLn(['TLazDocManager.GetElementChain i=',i,' CodeContext=',FindContextToString(LDElement.CodeContext)]);
CodePos:=PCodeXYPosition(ListOfPCodeXYPosition[i]);
DebugLn(['TLazDocManager.GetElementChain i=',i,' X=',CodePos^.X,' Y=',CodePos^.Y]);
if (CodePos=nil) or (CodePos^.Code=nil) or (CodePos^.X<1) or (CodePos^.Y<1)
then begin
DebugLn(['TLazDocManager.GetElementChain i=',i,' invalid CodePos']);
continue;
end;
// build CodeTree and find node
if not CodeToolBoss.Explore(CodePos^.Code,CurTool,false,true) then begin
DebugLn(['TLazDocManager.GetElementChain i=',i,' explore failed']);
continue;
end;
if CurTool.CaretToCleanPos(CodePos^,CleanPos)<>0 then begin
DebugLn(['TLazDocManager.GetElementChain i=',i,' invalid CodePos']);
continue;
end;
Node:=CurTool.FindDeepestNodeAtPos(CleanPos,false);
if Node=nil then begin
DebugLn(['TLazDocManager.GetElementChain i=',i,' node not found']);
continue;
end;
// use only definition nodes
if not (Node.Desc in (AllIdentifierDefinitions+[ctnProperty,ctnProcedure]))
then begin
DebugLn(['TLazDocManager.GetElementChain i=',i,' ignoring node ',Node.DescAsString]);
continue;
end;
if (CurTool.NodeIsForwardDeclaration(Node)) then begin
DebugLn(['TLazDocManager.GetElementChain i=',i,' ignoring forward']);
continue;
end;
// add element
LDElement:=Chain.Add;
LDElement.CodeContext.Tool:=CurTool;
LDElement.CodeContext.Node:=Node;
DebugLn(['TLazDocManager.GetElementChain i=',i,' CodeContext=',FindContextToString(LDElement.CodeContext)]);
// find corresponding FPDoc file
SrcFilename:=LDElement.CodeContext.Tool.MainFilename;
FPDocFilename:=GetFPDocFilenameForSource(SrcFilename,false,CacheWasUsed);
@ -619,12 +712,67 @@ begin
Result:=ldprSuccess;
finally
FreeListOfPFindContext(ListOfPFindContext);
FreeListOfPFindContext(ListOfPCodeXYPosition);
if Result<>ldprSuccess then
FreeAndNil(Chain);
end;
end;
function TLazDocManager.GetHint(Code: TCodeBuffer; X, Y: integer;
Complete: boolean; out Hint: string; out CacheWasUsed: boolean
): TLazDocParseResult;
function EndNow(var LastResult: TLazDocParseResult): boolean;
begin
if LastResult<>ldprSuccess then begin
Result:=true;
if Hint<>'' then
LastResult:=ldprSuccess
else
LastResult:=ldprFailed;
exit;
end;
if (not CacheWasUsed) and (not Complete) then begin
Result:=true;
LastResult:=ldprParsing;
end;
Result:=false;
end;
var
Chain: TLazDocElementChain;
i: Integer;
Item: TLazDocElement;
NodeValues: TFPDocNode;
begin
DebugLn(['TLazDocManager.GetHint ',Code.Filename,' ',X,',',Y]);
Hint:=CodeToolBoss.FindSmartHint(Code,X,Y);
CacheWasUsed:=true;
Chain:=nil;
try
DebugLn(['TLazDocManager.GetHint GetElementChain...']);
Result:=GetElementChain(Code,X,Y,Complete,Chain,CacheWasUsed);
if EndNow(Result) then exit;
if Chain<>nil then begin
for i:=0 to Chain.Count-1 do begin
Item:=Chain[i];
DebugLn(['TLazDocManager.GetHint ',i,' Element=',Item.ElementName]);
if Item.ElementNode=nil then continue;
NodeValues:=Item.FPDocFile.GetValuesFromNode(Item.ElementNode);
if NodeValues[fpdiShort]<>'' then begin
Hint:=Hint+#13#13+Item.ElementName+#13
+NodeValues[fpdiShort];
end;
end;
end;
Result:=ldprFailed;
finally
Chain.Free;
end;
end;
procedure TLazDocManager.FreeDocs;
var
AVLNode: TAvgLvlTreeNode;

View File

@ -53,16 +53,6 @@ uses
IDEProcs, LazarusIDEStrConsts, LazDocSelectInherited, LazDoc;
type
TFPDocItem = (
fpdiShort,
fpdiDescription,
fpdiErrors,
fpdiSeeAlso,
fpdiExample
);
TFPDocNode = array [TFPDocItem] of String;
TLazDocFormFlag = (
ldffCaptionNeedsUpdate,
ldffInheritedNeedsUpdate,