MG: fixed find declaration node cache flags checking and updates for defines

git-svn-id: trunk@1480 -
This commit is contained in:
lazarus 2002-03-06 17:26:52 +00:00
parent 969951d7fb
commit 84fc508f31
4 changed files with 566 additions and 102 deletions

View File

@ -489,6 +489,10 @@ function TCodeToolManager.HandleException(AnException: Exception): boolean;
var ErrorSrcTool: TCustomCodeTool; var ErrorSrcTool: TCustomCodeTool;
begin begin
fErrorMsg:=AnException.Message; fErrorMsg:=AnException.Message;
if not ((AnException is ELinkScannerError) or (AnException is ECodeToolError))
then begin
FErrorMsg:=AnException.ClassName+': '+FErrorMsg;
end;
if (AnException is ELinkScannerError) then begin if (AnException is ELinkScannerError) then begin
fErrorCode:=TCodeBuffer(ELinkScannerError(AnException).Sender.Code); fErrorCode:=TCodeBuffer(ELinkScannerError(AnException).Sender.Code);
if fErrorCode<>nil then if fErrorCode<>nil then

View File

@ -101,7 +101,6 @@ const
'UndefineAll', 'If', 'IfDef', 'IfNDef', 'ElseIf', 'Else', 'Directory' 'UndefineAll', 'If', 'IfDef', 'IfNDef', 'ElseIf', 'Else', 'Directory'
); );
type type
TDefineTemplateFlag = (dtfAutoGenerated, dtfProjectSpecific); TDefineTemplateFlag = (dtfAutoGenerated, dtfProjectSpecific);
TDefineTemplateFlags = set of TDefineTemplateFlag; TDefineTemplateFlags = set of TDefineTemplateFlag;
@ -133,6 +132,7 @@ type
property Prior: TDefineTemplate read FPrior; property Prior: TDefineTemplate read FPrior;
property FirstChild: TDefineTemplate read FFirstChild; property FirstChild: TDefineTemplate read FFirstChild;
property LastChild: TDefineTemplate read FLastChild; property LastChild: TDefineTemplate read FLastChild;
property Marked: boolean read FMarked write FMarked;
procedure AddChild(ADefineTemplate: TDefineTemplate); procedure AddChild(ADefineTemplate: TDefineTemplate);
procedure InsertBehind(APrior: TDefineTemplate); procedure InsertBehind(APrior: TDefineTemplate);
@ -142,18 +142,26 @@ type
function IsEqual(ADefineTemplate: TDefineTemplate; function IsEqual(ADefineTemplate: TDefineTemplate;
CheckSubNodes, CheckNextSiblings: boolean): boolean; CheckSubNodes, CheckNextSiblings: boolean): boolean;
function CreateCopy(OnlyMarked: boolean): TDefineTemplate; function CreateCopy(OnlyMarked: boolean): TDefineTemplate;
function FindRoot: TDefineTemplate;
function FindChildByName(const AName: string): TDefineTemplate; function FindChildByName(const AName: string): TDefineTemplate;
function FindByName(const AName: string; function FindByName(const AName: string;
WithSubChilds, WithNextSiblings: boolean): TDefineTemplate; WithSubChilds, WithNextSiblings: boolean): TDefineTemplate;
function LoadFromXMLConfig(XMLConfig: TXMLConfig; function FindUniqueName(const Prefix: string): string;
const Path: string): boolean; function LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string): boolean;
procedure LoadValuesFromXMLConfig(XMLConfig: TXMLConfig; const Path: string);
procedure SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string; procedure SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string;
OnlyMarked, WithMergeInfo: boolean); OnlyMarked, WithMergeInfo: boolean);
class procedure MergeXMLConfig(ParentDefTempl: TDefineTemplate;
var FirstSibling,LastSibling:TDefineTemplate;
XMLConfig: TXMLConfig; const Path, NewNamePrefix: string);
function SelfOrParentContainsFlag(AFlag: TDefineTemplateFlag): boolean; function SelfOrParentContainsFlag(AFlag: TDefineTemplateFlag): boolean;
function IsAutoGenerated: boolean; function IsAutoGenerated: boolean;
function IsProjectSpecific: boolean; function IsProjectSpecific: boolean;
procedure MarkAllNonAutoNonProjSpecNodes; procedure MarkGlobals;
procedure MarkAllNonAutoProjSpecNodes; procedure MarkProjectSpecificOnly;
procedure MarkProjectSpecificAndParents;
procedure MarkNonAutoCreated;
procedure RemoveMarked;
procedure Unbind; procedure Unbind;
procedure Clear; procedure Clear;
constructor Create; constructor Create;
@ -184,7 +192,12 @@ type
dtspProjectSpecific, // save all (not auto) and project specific nodes dtspProjectSpecific, // save all (not auto) and project specific nodes
dtspGlobals // save all (not auto) and (not proj spec) nodes dtspGlobals // save all (not auto) and (not proj spec) nodes
); );
TDefineTreeLoadPolicy = (
dtlpAll, // replace all DefineTemplates
dtlpProjectSpecific, // replace all (not auto) and project specific nodes
dtlpGlobals // replace all (not auto) and (not proj spec) nodes
);
TDefineTree = class TDefineTree = class
private private
FFirstDefineTemplate: TDefineTemplate; FFirstDefineTemplate: TDefineTemplate;
@ -193,8 +206,9 @@ type
FOnReadValue: TOnReadValue; FOnReadValue: TOnReadValue;
FErrorTemplate: TDefineTemplate; FErrorTemplate: TDefineTemplate;
FErrorDescription: string; FErrorDescription: string;
function FindDirectoryInCache(const Path: string): TDirectoryDefines;
function Calculate(DirDef: TDirectoryDefines): boolean; function Calculate(DirDef: TDirectoryDefines): boolean;
protected
function FindDirectoryInCache(const Path: string): TDirectoryDefines;
public public
function GetDefinesForDirectory(const Path: string): TExpressionEvaluator; function GetDefinesForDirectory(const Path: string): TExpressionEvaluator;
function GetDefinesForVirtualDirectory: TExpressionEvaluator; function GetDefinesForVirtualDirectory: TExpressionEvaluator;
@ -211,13 +225,19 @@ type
property ErrorTemplate: TDefineTemplate read FErrorTemplate; property ErrorTemplate: TDefineTemplate read FErrorTemplate;
property ErrorDescription: string read FErrorDescription; property ErrorDescription: string read FErrorDescription;
function LoadFromXMLConfig(XMLConfig: TXMLConfig; function LoadFromXMLConfig(XMLConfig: TXMLConfig;
const Path: string; Policy: TDefineTreeSavePolicy): boolean; const Path: string; Policy: TDefineTreeLoadPolicy;
const NewNamePrefix: string): boolean;
function SaveToXMLConfig(XMLConfig: TXMLConfig; function SaveToXMLConfig(XMLConfig: TXMLConfig;
const Path: string; Policy: TDefineTreeSavePolicy): boolean; const Path: string; Policy: TDefineTreeSavePolicy): boolean;
procedure ClearCache; procedure ClearCache;
procedure Clear; procedure Clear;
function IsEqual(SrcDefineTree: TDefineTree): boolean; function IsEqual(SrcDefineTree: TDefineTree): boolean;
procedure Assign(SrcDefineTree: TDefineTree); procedure Assign(SrcDefineTree: TDefineTree);
procedure RemoveMarked;
procedure RemoveGlobals;
procedure RemoveProjectSpecificOnly;
procedure RemoveProjectSpecificAndParents;
procedure RemoveNonAutoCreated;
constructor Create; constructor Create;
destructor Destroy; override; destructor Destroy; override;
function ConsistencyCheck: integer; // 0 = ok function ConsistencyCheck: integer; // 0 = ok
@ -257,6 +277,7 @@ const
); );
function DefineActionNameToAction(const s: string): TDefineAction; function DefineActionNameToAction(const s: string): TDefineAction;
function DefineTemplateFlagsToString(Flags: TDefineTemplateFlags): string;
implementation implementation
@ -279,6 +300,18 @@ begin
Result:=da_None; Result:=da_None;
end; end;
function DefineTemplateFlagsToString(Flags: TDefineTemplateFlags): string;
var f: TDefineTemplateFlag;
begin
Result:='';
for f:=Low(TDefineTemplateFlag) to High(TDefineTemplateFlag) do begin
if f in Flags then begin
if Result<>'' then Result:=Result+',';
Result:=Result+DefineTemplateFlagNames[f];
end;
end;
end;
function CompareFilenames(const FileName1, Filename2: string): integer; function CompareFilenames(const FileName1, Filename2: string): integer;
begin begin
{$ifdef CaseInsensitiveFilenames} {$ifdef CaseInsensitiveFilenames}
@ -423,14 +456,14 @@ procedure TDefineTemplate.ComputeChildFlags;
// accumulate flags of all childs in FChildFlags // accumulate flags of all childs in FChildFlags
var ANode: TDefineTemplate; var ANode: TDefineTemplate;
begin begin
FChildFlags:=[];
ANode:=Self; ANode:=Self;
while ANode<>nil do begin while ANode<>nil do begin
if ANode.FirstChild<>nil then begin ANode.FChildFlags:=[];
if ANode.FirstChild<>nil then
ANode.FirstChild.ComputeChildFlags; ANode.FirstChild.ComputeChildFlags;
FChildFlags:=FChildFlags+ANode.FirstChild.FChildFlags if ANode.Parent<>nil then
+ANode.FirstChild.Flags; ANode.Parent.FChildFlags:=ANode.Parent.FChildFlags
end; +ANode.Flags+ANode.FChildFlags;
ANode:=ANode.Next; ANode:=ANode.Next;
end; end;
end; end;
@ -439,19 +472,19 @@ procedure TDefineTemplate.ComputeParentFlags;
// accumulate flags of all parents in FParentFlags // accumulate flags of all parents in FParentFlags
var ANode: TDefineTemplate; var ANode: TDefineTemplate;
begin begin
if Parent<>nil then
FParentFlags:=Parent.Flags+Parent.FParentFlags
else
FParentFlags:=[];
ANode:=Self; ANode:=Self;
while ANode<>nil do begin while ANode<>nil do begin
if ANode.Parent<>nil then
ANode.FParentFlags:=ANode.Parent.Flags+ANode.Parent.FParentFlags
else
ANode.FParentFlags:=[];
if ANode.FirstChild<>nil then if ANode.FirstChild<>nil then
ANode.FirstChild.ComputeParentFlags; ANode.FirstChild.ComputeParentFlags;
ANode:=ANode.Next; ANode:=ANode.Next;
end; end;
end; end;
procedure TDefineTemplate.MarkAllNonAutoNonProjSpecNodes; procedure TDefineTemplate.MarkGlobals;
// mark every node, that itself and its parents are not auto generated and // mark every node, that itself and its parents are not auto generated and
// not project specific // not project specific
var ANode: TDefineTemplate; var ANode: TDefineTemplate;
@ -462,14 +495,32 @@ begin
ANode.FMarked:=((ANode.Flags+ANode.FParentFlags) ANode.FMarked:=((ANode.Flags+ANode.FParentFlags)
*[dtfAutoGenerated,dtfProjectSpecific]=[]); *[dtfAutoGenerated,dtfProjectSpecific]=[]);
if ANode.FirstChild<>nil then if ANode.FirstChild<>nil then
ANode.FirstChild.MarkAllNonAutoNonProjSpecNodes; ANode.FirstChild.MarkGlobals;
ANode:=ANode.Next; ANode:=ANode.Next;
end; end;
end; end;
procedure TDefineTemplate.MarkAllNonAutoProjSpecNodes; procedure TDefineTemplate.MarkProjectSpecificOnly;
// mark every node, that itself and its parents are not auto generated and
// itself or one of its parents is project specific
var ANode: TDefineTemplate;
begin
ComputeParentFlags;
ComputeChildFlags;
ANode:=Self;
while ANode<>nil do begin
ANode.FMarked:=((ANode.Flags+ANode.FParentFlags)*[dtfAutoGenerated]=[])
and (dtfProjectSpecific in (ANode.Flags+ANode.FParentFlags));
if ANode.FirstChild<>nil then
ANode.FirstChild.MarkProjectSpecificOnly;
ANode:=ANode.Next;
end;
end;
procedure TDefineTemplate.MarkProjectSpecificAndParents;
// mark every node, that itself and its parents are not auto generated and // mark every node, that itself and its parents are not auto generated and
// itself or one of its parents or one of its childs is project specific // itself or one of its parents or one of its childs is project specific
// Note: this can contain globals with project specific childs
var ANode: TDefineTemplate; var ANode: TDefineTemplate;
begin begin
ComputeParentFlags; ComputeParentFlags;
@ -480,11 +531,44 @@ begin
and (dtfProjectSpecific and (dtfProjectSpecific
in (ANode.Flags+ANode.FParentFlags+ANode.FChildFlags)); in (ANode.Flags+ANode.FParentFlags+ANode.FChildFlags));
if ANode.FirstChild<>nil then if ANode.FirstChild<>nil then
ANode.FirstChild.MarkAllNonAutoProjSpecNodes; ANode.FirstChild.MarkProjectSpecificAndParents;
ANode:=ANode.Next; ANode:=ANode.Next;
end; end;
end; end;
procedure TDefineTemplate.MarkNonAutoCreated;
// mark every node, that itself and its parent are not auto generated
var ANode: TDefineTemplate;
begin
ComputeParentFlags;
ANode:=Self;
while ANode<>nil do begin
ANode.FMarked:=not (dtfAutoGenerated in (ANode.Flags+ANode.FParentFlags));
if ANode.FirstChild<>nil then
ANode.FirstChild.MarkNonAutoCreated;
ANode:=ANode.Next;
end;
end;
procedure TDefineTemplate.RemoveMarked;
var ANode, NextNode: TDefineTemplate;
begin
ANode:=Self;
while ANode<>nil do begin
NextNode:=ANode.Next;
if ANode.FMarked then begin
writeln(' REMOVING ',ANode.Name);
ANode.Unbind;
ANode.Free;
end else begin
if ANode.FirstChild<>nil then begin
ANode.FirstChild.RemoveMarked;
end;
end;
ANode:=NextNode;
end;
end;
procedure TDefineTemplate.AddChild(ADefineTemplate: TDefineTemplate); procedure TDefineTemplate.AddChild(ADefineTemplate: TDefineTemplate);
// add as last child // add as last child
begin begin
@ -573,7 +657,6 @@ procedure TDefineTemplate.Assign(ADefineTemplate: TDefineTemplate;
WithSubNodes, WithNextSiblings: boolean); WithSubNodes, WithNextSiblings: boolean);
var ChildTemplate, CopyTemplate, NextTemplate: TDefineTemplate; var ChildTemplate, CopyTemplate, NextTemplate: TDefineTemplate;
begin begin
if IsEqual(ADefineTemplate,WithSubNodes,WithNextSiblings) then exit;
Clear; Clear;
if ADefineTemplate=nil then exit; if ADefineTemplate=nil then exit;
Name:=ADefineTemplate.Name; Name:=ADefineTemplate.Name;
@ -670,6 +753,19 @@ begin
//writeln('TDefineTemplate.CreateCopy B ',ConsistencyCheck); //writeln('TDefineTemplate.CreateCopy B ',ConsistencyCheck);
end; end;
function TDefineTemplate.FindRoot: TDefineTemplate;
begin
Result:=Self;
repeat
if Result.Parent<>nil then
Result:=Result.Parent
else if Result.Prior<>nil then
Result:=Result.Prior
else
break;
until false;
end;
destructor TDefineTemplate.Destroy; destructor TDefineTemplate.Destroy;
begin begin
Clear; Clear;
@ -679,10 +775,10 @@ end;
function TDefineTemplate.LoadFromXMLConfig(XMLConfig: TXMLConfig; function TDefineTemplate.LoadFromXMLConfig(XMLConfig: TXMLConfig;
const Path: string): boolean; const Path: string): boolean;
// obsolete
var IndexedPath: string; var IndexedPath: string;
i, LvlCount: integer; i, LvlCount: integer;
DefTempl, LastDefTempl: TDefineTemplate; DefTempl, LastDefTempl: TDefineTemplate;
f: TDefineTemplateFlag;
begin begin
Clear; Clear;
LvlCount:=XMLConfig.GetValue(Path+'Count/Value',0); LvlCount:=XMLConfig.GetValue(Path+'Count/Value',0);
@ -701,20 +797,8 @@ begin
inc(DefTempl.FParent.FChildCount); inc(DefTempl.FParent.FChildCount);
end; end;
end; end;
IndexedPath:=Path+IntToStr(i)+'/'; IndexedPath:=Path+'Node'+IntToStr(i)+'/';
DefTempl.Name:=XMLConfig.GetValue(IndexedPath+'Name/Value','no name'); DefTempl.LoadValuesFromXMLConfig(XMLConfig,IndexedPath);
DefTempl.Description:=XMLConfig.GetValue(IndexedPath+'Description/Value','');
DefTempl.Value:=XMLConfig.GetValue(IndexedPath+'Value/Value','');
DefTempl.Variable:=XMLConfig.GetValue(IndexedPath+'Variable/Value','');
DefTempl.Action:=DefineActionNameToAction(
XMLConfig.GetValue(IndexedPath+'Action/Value',''));
Flags:=[];
for f:=Low(TDefineTemplateFlag) to High(TDefineTemplateFlag) do begin
if XMLConfig.GetValue(IndexedPath+'Flags/'+DefineTemplateFlagNames[f]
+'/Value',false)
then
Include(Flags,f);
end;
// load childs // load childs
if XMLConfig.GetValue(IndexedPath+'Count/Value',0)>0 then begin if XMLConfig.GetValue(IndexedPath+'Count/Value',0)>0 then begin
FFirstChild:=TDefineTemplate.Create; FFirstChild:=TDefineTemplate.Create;
@ -726,6 +810,25 @@ begin
Result:=true; Result:=true;
end; end;
procedure TDefineTemplate.LoadValuesFromXMLConfig(XMLConfig: TXMLConfig;
const Path: string);
var f: TDefineTemplateFlag;
begin
Name:=XMLConfig.GetValue(Path+'Name/Value','no name');
Description:=XMLConfig.GetValue(Path+'Description/Value','');
Value:=XMLConfig.GetValue(Path+'Value/Value','');
Variable:=XMLConfig.GetValue(Path+'Variable/Value','');
Action:=DefineActionNameToAction(
XMLConfig.GetValue(Path+'Action/Value',''));
Flags:=[];
for f:=Low(TDefineTemplateFlag) to High(TDefineTemplateFlag) do begin
if (f<>dtfAutoGenerated)
and (XMLConfig.GetValue(Path+'Flags/'+DefineTemplateFlagNames[f],false))
then
Include(Flags,f);
end;
end;
procedure TDefineTemplate.SaveToXMLConfig(XMLConfig: TXMLConfig; procedure TDefineTemplate.SaveToXMLConfig(XMLConfig: TXMLConfig;
const Path: string; OnlyMarked, WithMergeInfo: boolean); const Path: string; OnlyMarked, WithMergeInfo: boolean);
var IndexedPath, MergeNameInFront, MergeNameBehind: string; var IndexedPath, MergeNameInFront, MergeNameBehind: string;
@ -745,7 +848,7 @@ begin
if (DefTempl.FMarked) or (not OnlyMarked) then begin if (DefTempl.FMarked) or (not OnlyMarked) then begin
// save node // save node
inc(Index); inc(Index);
IndexedPath:=Path+IntToStr(Index)+'/'; IndexedPath:=Path+'Node'+IntToStr(Index)+'/';
XMLConfig.SetValue(IndexedPath+'Name/Value',DefTempl.Name); XMLConfig.SetValue(IndexedPath+'Name/Value',DefTempl.Name);
XMLConfig.SetValue(IndexedPath+'Description/Value',DefTempl.Description); XMLConfig.SetValue(IndexedPath+'Description/Value',DefTempl.Description);
XMLConfig.SetValue(IndexedPath+'Value/Value',DefTempl.Value); XMLConfig.SetValue(IndexedPath+'Value/Value',DefTempl.Value);
@ -753,8 +856,9 @@ begin
XMLConfig.SetValue(IndexedPath+'Action/Value', XMLConfig.SetValue(IndexedPath+'Action/Value',
DefineActionNames[DefTempl.Action]); DefineActionNames[DefTempl.Action]);
for f:=Low(TDefineTemplateFlag) to High(TDefineTemplateFlag) do begin for f:=Low(TDefineTemplateFlag) to High(TDefineTemplateFlag) do begin
XMLConfig.SetValue(IndexedPath+'Flags/'+DefineTemplateFlagNames[f] if (f<>dtfAutoGenerated) then
,f in Flags); XMLConfig.SetValue(IndexedPath+'Flags/'+DefineTemplateFlagNames[f]
,f in DefTempl.Flags);
end; end;
if WithMergeInfo then begin if WithMergeInfo then begin
if DefTempl.Prior<>nil then if DefTempl.Prior<>nil then
@ -771,15 +875,120 @@ begin
MergeNameBehind); MergeNameBehind);
end; end;
// save childs // save childs
if FFirstChild<>nil then if DefTempl.FFirstChild<>nil then
FirstChild.SaveToXMLConfig(XMLConfig,IndexedPath, DefTempl.FirstChild.SaveToXMLConfig(XMLConfig,IndexedPath,
OnlyMarked,WithMergeInfo); OnlyMarked,WithMergeInfo)
else
XMLConfig.SetValue(IndexedPath+'Count/Value',0);
end; end;
DefTempl:=DefTempl.Next; DefTempl:=DefTempl.Next;
until DefTempl=nil; until DefTempl=nil;
XMLConfig.SetValue(Path+'Count/Value',Index); XMLConfig.SetValue(Path+'Count/Value',Index);
end; end;
procedure TDefineTemplate.MergeXMLConfig(ParentDefTempl: TDefineTemplate;
var FirstSibling, LastSibling: TDefineTemplate;
XMLConfig: TXMLConfig; const Path, NewNamePrefix: string);
var i, NewCount: integer;
NewNode, PosNode: TDefineTemplate;
MergeNameInFront, MergeNameBehind, IndexedPath: string;
Inserted: boolean;
begin
NewCount:=XMLConfig.GetValue(Path+'Count/Value',0);
if NewCount=0 then exit;
for i:=1 to NewCount do begin
// load each node and merge it
IndexedPath:=Path+'Node'+IntToStr(i)+'/';
NewNode:=TDefineTemplate.Create;
NewNode.LoadValuesFromXMLConfig(XMLConfig,IndexedPath);
Inserted:=false;
if NewNode.Name<>'' then begin
// node has a name -> test if already exists
PosNode:=FirstSibling;
while (PosNode<>nil)
and (AnsiCompareText(PosNode.Name,NewNode.Name)<>0) do
PosNode:=PosNode.Next;
if PosNode<>nil then begin
// node with same name already exists -> check if it is a copy
if NewNode.IsEqual(PosNode,false,false) then begin
// node already exists
NewNode.Free;
NewNode:=PosNode;
end else begin
// node has same name, but different values
// -> rename node
NewNode.Name:=NewNode.FindUniqueName(NewNamePrefix);
if (not PosNode.IsProjectSpecific) or (NewNode.IsProjectSpecific) then
begin
// insert behind PosNode
NewNode.InsertBehind(PosNode);
end else begin
// insert global NewNode in front of project specific PosNode
NewNode.InsertInFront(PosNode);
end;
end;
Inserted:=true;
end;
end;
if not Inserted then begin
// node name is unique or empty -> insert node
MergeNameInFront:=XMLConfig.GetValue(
IndexedPath+'MergeNameInFront/Value','');
if MergeNameInFront<>'' then begin
// last time, node was inserted behind MergeNameInFront
// -> search MergeNameInFront
PosNode:=LastSibling;
while (PosNode<>nil)
and (AnsiCompareText(PosNode.Name,MergeNameInFront)<>0) do
PosNode:=PosNode.Prior;
if PosNode<>nil then begin
// MergeNameInFront found -> insert behind
NewNode.InsertBehind(PosNode);
Inserted:=true;
end;
end;
if not Inserted then begin
MergeNameBehind:=XMLConfig.GetValue(
IndexedPath+'MergeNameBehind/Value','');
if MergeNameBehind<>'' then begin
// last time, node was inserted in front of MergeNameBehind
// -> search MergeNameBehind
PosNode:=FirstSibling;
while (PosNode<>nil)
and (AnsiCompareText(PosNode.Name,MergeNameBehind)<>0) do
PosNode:=PosNode.Next;
if PosNode<>nil then begin
// MergeNameBehind found -> insert in front
NewNode.InsertInFront(PosNode);
Inserted:=true;
end;
end;
end;
if not Inserted then begin
// no merge position found -> add as last
if LastSibling<>nil then begin
NewNode.InsertBehind(LastSibling);
end else if ParentDefTempl<>nil then begin
ParentDefTempl.AddChild(NewNode);
end;
end;
end;
// NewNode is now inserted -> update FirstSibling and LastSibling
if FirstSibling=nil then begin
FirstSibling:=NewNode;
LastSibling:=NewNode;
end else begin
while FirstSibling.Prior<>nil do
FirstSibling:=FirstSibling.Prior;
while LastSibling.Next<>nil do
LastSibling:=LastSibling.Next;
end;
// insert childs
MergeXMLConfig(NewNode,NewNode.FFirstChild,NewNode.FLastChild,
XMLConfig,IndexedPath,NewNamePrefix);
end;
end;
function TDefineTemplate.ConsistencyCheck: integer; function TDefineTemplate.ConsistencyCheck: integer;
var RealChildCount: integer; var RealChildCount: integer;
DefTempl: TDefineTemplate; DefTempl: TDefineTemplate;
@ -832,15 +1041,20 @@ procedure TDefineTemplate.WriteDebugReport;
if ANode=nil then exit; if ANode=nil then exit;
ActionStr:=DefineActionNames[ANode.Action]; ActionStr:=DefineActionNames[ANode.Action];
writeln(Prefix,'Self=',HexStr(Cardinal(ANode),8), writeln(Prefix,'Self=',HexStr(Cardinal(ANode),8),
' Name="',ANode.Name,'"',
' Consistency=',ANode.ConsistencyCheck, ' Consistency=',ANode.ConsistencyCheck,
' Next=',HexStr(Cardinal(ANode.Next),8), ' Next=',HexStr(Cardinal(ANode.Next),8),
' Prior=',HexStr(Cardinal(ANode.Prior),8), ' Prior=',HexStr(Cardinal(ANode.Prior),8),
' Action=',ActionStr, ' Action=',ActionStr,
' Name="',ANode.Name,'"'); ' Flags=[',DefineTemplateFlagsToString(ANode.Flags),']',
' FParentFlags=[',DefineTemplateFlagsToString(ANode.FParentFlags),']',
' FChildFlags=[',DefineTemplateFlagsToString(ANode.FChildFlags),']',
' Marked=',ANode.Marked
);
writeln(Prefix+' + Description="',ANode.Description,'"'); writeln(Prefix+' + Description="',ANode.Description,'"');
writeln(Prefix+' + Variable="',ANode.Variable,'"'); writeln(Prefix+' + Variable="',ANode.Variable,'"');
writeln(Prefix+' + Value="',ANode.Value,'"'); writeln(Prefix+' + Value="',ANode.Value,'"');
WriteNode(ANode.FFirstChild,Prefix+' '); WriteNode(ANode.FirstChild,Prefix+' ');
WriteNode(ANode.Next,Prefix); WriteNode(ANode.Next,Prefix);
end; end;
@ -858,9 +1072,12 @@ begin
and (Variable=ADefineTemplate.Variable) and (Variable=ADefineTemplate.Variable)
and (Value=ADefineTemplate.Value) and (Value=ADefineTemplate.Value)
and (Action=ADefineTemplate.Action) and (Action=ADefineTemplate.Action)
and (Flags=ADefineTemplate.Flags) and (Flags=ADefineTemplate.Flags);
and (ChildCount=ADefineTemplate.ChildCount);
if Result and CheckSubNodes then begin if Result and CheckSubNodes then begin
if (ChildCount<>ADefineTemplate.ChildCount) then begin
Result:=false;
exit;
end;
SrcNode:=FirstChild; SrcNode:=FirstChild;
DestNode:=ADefineTemplate.FirstChild; DestNode:=ADefineTemplate.FirstChild;
if SrcNode<>nil then if SrcNode<>nil then
@ -869,8 +1086,13 @@ begin
if Result and CheckNextSiblings then begin if Result and CheckNextSiblings then begin
SrcNode:=Next; SrcNode:=Next;
DestNode:=ADefineTemplate.Next; DestNode:=ADefineTemplate.Next;
if SrcNode<>nil then while (SrcNode<>nil) and (DestNode<>nil) do begin
Result:=SrcNode.IsEqual(DestNode,CheckSubNodes,CheckNextSiblings); Result:=SrcNode.IsEqual(DestNode,CheckSubNodes,false);
if not Result then exit;
SrcNode:=SrcNode.Next;
DestNode:=DestNode.Next;
end;
Result:=(SrcNode=nil) and (DestNode=nil);
end; end;
end; end;
@ -940,6 +1162,18 @@ begin
end; end;
end; end;
function TDefineTemplate.FindUniqueName(const Prefix: string): string;
var Root: TDefineTemplate;
i: integer;
begin
Root:=FindRoot;
i:=0;
repeat
inc(i);
Result:=Prefix+IntToStr(i);
until Root.FindByName(Result,true,true)=nil;
end;
{ TDirectoryDefines } { TDirectoryDefines }
@ -969,12 +1203,14 @@ end;
function TDefineTree.IsEqual(SrcDefineTree: TDefineTree): boolean; function TDefineTree.IsEqual(SrcDefineTree: TDefineTree): boolean;
begin begin
Result:=false; Result:=false;
if SrcDefineTree=nil then exit;
if (FFirstDefineTemplate=nil) xor (SrcDefineTree.FFirstDefineTemplate=nil) if (FFirstDefineTemplate=nil) xor (SrcDefineTree.FFirstDefineTemplate=nil)
then exit; then exit;
if (FFirstDefineTemplate<>nil) if (FFirstDefineTemplate<>nil)
and (not FFirstDefineTemplate.IsEqual( and (not FFirstDefineTemplate.IsEqual(
SrcDefineTree.FFirstDefineTemplate,true,true)) SrcDefineTree.FFirstDefineTemplate,true,true))
then exit; then exit;
Result:=true;
end; end;
procedure TDefineTree.Assign(SrcDefineTree: TDefineTree); procedure TDefineTree.Assign(SrcDefineTree: TDefineTree);
@ -1029,6 +1265,45 @@ begin
Result:=nil; Result:=nil;
end; end;
procedure TDefineTree.RemoveMarked;
var NewFirstNode: TDefineTemplate;
begin
if FFirstDefineTemplate=nil then exit;
NewFirstNode:=FFirstDefineTemplate;
while (NewFirstNode<>nil) and NewFirstNode.Marked do
NewFirstNode:=NewFirstNode.Next;
FFirstDefineTemplate.RemoveMarked;
FFirstDefineTemplate:=NewFirstNode;
end;
procedure TDefineTree.RemoveGlobals;
begin
if FFirstDefineTemplate=nil then exit;
FFirstDefineTemplate.MarkGlobals;
RemoveMarked;
end;
procedure TDefineTree.RemoveProjectSpecificOnly;
begin
if FFirstDefineTemplate=nil then exit;
FFirstDefineTemplate.MarkProjectSpecificOnly;
RemoveMarked;
end;
procedure TDefineTree.RemoveProjectSpecificAndParents;
begin
if FFirstDefineTemplate=nil then exit;
FFirstDefineTemplate.MarkProjectSpecificAndParents;
RemoveMarked;
end;
procedure TDefineTree.RemoveNonAutoCreated;
begin
if FFirstDefineTemplate=nil then exit;
FFirstDefineTemplate.MarkNonAutoCreated;
RemoveMarked;
end;
function TDefineTree.GetDefinesForDirectory( function TDefineTree.GetDefinesForDirectory(
const Path: string): TExpressionEvaluator; const Path: string): TExpressionEvaluator;
var ExpPath: string; var ExpPath: string;
@ -1291,34 +1566,39 @@ begin
end; end;
function TDefineTree.LoadFromXMLConfig(XMLConfig: TXMLConfig; function TDefineTree.LoadFromXMLConfig(XMLConfig: TXMLConfig;
const Path: string; Policy: TDefineTreeSavePolicy): boolean; const Path: string; Policy: TDefineTreeLoadPolicy;
const NewNamePrefix: string): boolean;
var LastDefTempl: TDefineTemplate;
begin begin
case Policy of case Policy of
dtspGlobals: dtlpGlobals:
begin begin
// replace globals // replace globals
RemoveGlobals;
end; end;
dtspProjectSpecific: dtlpProjectSpecific:
begin begin
// replace project specific // replace project specific
RemoveProjectSpecificOnly;
end; end;
else else
begin begin
// replace all // replace all
FreeAndNil(FFirstDefineTemplate); FreeAndNil(FFirstDefineTemplate);
if XMLConfig.GetValue(Path+'/Count/Value',0)>0 then begin
FFirstDefineTemplate:=TDefineTemplate.Create;
Result:=FFirstDefineTemplate.LoadFromXMLConfig(XMLConfig,Path);
end else begin
Result:=true;
end;
end; end;
end; end;
// import new defines
LastDefTempl:=FFirstDefineTemplate;
if LastDefTempl<>nil then begin
while LastDefTempl.Next<>nil do
LastDefTempl:=LastDefTempl.Next;
end;
TDefineTemplate.MergeXMLConfig(nil,FFirstDefineTemplate,LastDefTempl,
XMLConfig,Path,NewNamePrefix);
Result:=true;
end; end;
function TDefineTree.SaveToXMLConfig(XMLConfig: TXMLConfig; function TDefineTree.SaveToXMLConfig(XMLConfig: TXMLConfig;
@ -1331,13 +1611,13 @@ begin
case Policy of case Policy of
dtspProjectSpecific: dtspProjectSpecific:
begin begin
FFirstDefineTemplate.MarkAllNonAutoProjSpecNodes; FFirstDefineTemplate.MarkProjectSpecificAndParents;
FFirstDefineTemplate.SaveToXMLConfig(XMLConfig,Path,true,true); FFirstDefineTemplate.SaveToXMLConfig(XMLConfig,Path,true,true);
end; end;
dtspGlobals: dtspGlobals:
begin begin
FFirstDefineTemplate.MarkAllNonAutoNonProjSpecNodes; FFirstDefineTemplate.MarkGlobals;
FFirstDefineTemplate.SaveToXMLConfig(XMLConfig,Path,true,true); FFirstDefineTemplate.SaveToXMLConfig(XMLConfig,Path,true,true);
end; end;
else else

View File

@ -46,7 +46,7 @@ interface
{ $DEFINE ShowTriedIdentifiers} { $DEFINE ShowTriedIdentifiers}
{ $DEFINE ShowExprEval} { $DEFINE ShowExprEval}
{ $DEFINE ShowFoundIdentifier} { $DEFINE ShowFoundIdentifier}
{ $DEFINE ShowCachedIdentifiers} { $DEFINE ShowInterfaceCache}
{ $DEFINE ShowNodeCache} { $DEFINE ShowNodeCache}
{ $DEFINE ShowBaseTypeCache} { $DEFINE ShowBaseTypeCache}
@ -269,6 +269,8 @@ type
Params: TFindDeclarationParams): boolean; Params: TFindDeclarationParams): boolean;
function FindIdentifierInUsedUnit(const AnUnitName: string; function FindIdentifierInUsedUnit(const AnUnitName: string;
Params: TFindDeclarationParams): boolean; Params: TFindDeclarationParams): boolean;
protected
function NodeIsInAMethod(Node: TCodeTreeNode): boolean;
protected protected
procedure DoDeleteNodes; override; procedure DoDeleteNodes; override;
procedure ClearNodeCaches(Force: boolean); procedure ClearNodeCaches(Force: boolean);
@ -923,6 +925,7 @@ var
LastNodeCache: TCodeTreeNodeCache; LastNodeCache: TCodeTreeNodeCache;
LastCacheEntry: PCodeTreeNodeCacheEntry; LastCacheEntry: PCodeTreeNodeCacheEntry;
SearchRangeFlags: TNodeCacheEntryFlags; SearchRangeFlags: TNodeCacheEntryFlags;
NodeCacheEntryFlags: TNodeCacheEntryFlags;
function FindInNodeCache: boolean; function FindInNodeCache: boolean;
var var
@ -934,7 +937,7 @@ var
// NodeCache changed -> search nearest cache entry for the identifier // NodeCache changed -> search nearest cache entry for the identifier
LastNodeCache:=NodeCache; LastNodeCache:=NodeCache;
if NodeCache<>nil then begin if NodeCache<>nil then begin
LastCacheEntry:=NodeCache.FindNearest(Params.identifier, LastCacheEntry:=NodeCache.FindNearest(Params.Identifier,
ContextNode.StartPos,ContextNode.EndPos, ContextNode.StartPos,ContextNode.EndPos,
not (fdfSearchForward in Params.Flags)); not (fdfSearchForward in Params.Flags));
end else end else
@ -943,22 +946,36 @@ var
if (LastCacheEntry<>nil) if (LastCacheEntry<>nil)
and (LastCacheEntry^.CleanStartPos<ContextNode.EndPos) and (LastCacheEntry^.CleanStartPos<ContextNode.EndPos)
and (LastCacheEntry^.CleanEndPos>ContextNode.StartPos) and (LastCacheEntry^.CleanEndPos>ContextNode.StartPos)
and ((NodeCacheEntryFlags-LastCacheEntry^.Flags)=[])
then begin then begin
// cached result found // cached result found
Params.SetResult(LastCacheEntry); Params.SetResult(LastCacheEntry);
{$IFDEF ShowNodeCache} {$IFDEF ShowNodeCache}
writeln(':::: TFindDeclarationTool.FindIdentifierInContext.FindInNodeCache'); writeln(':::: TFindDeclarationTool.FindIdentifierInContext.FindInNodeCache');
writeln(' Ident=',GetIdentifier(Params.Identifier), writeln(' Ident=',GetIdentifier(Params.Identifier),
' ContextNode=',ContextNode.DescAsString, ' ContextNode=',ContextNode.DescAsString,
' Self=',MainFilename); ' Self=',MainFilename);
if (Params.NewNode<>nil) then if (Params.NewNode<>nil) then
writeln(' NewTool=',Params.NewCodeTool.MainFilename, writeln(' NewTool=',Params.NewCodeTool.MainFilename,
' NewNode=',Params.NewNode.DescAsString); ' NewNode=',Params.NewNode.DescAsString)
else
writeln(' cache says: identifier NOT FOUND');
{$ENDIF} {$ENDIF}
Result:=true; Result:=true;
end; end;
end; end;
procedure SetResultBeforeExit(NewResult: boolean);
begin
FindIdentifierInContext:=NewResult;
if not NewResult and (fdfExceptionOnNotFound in Params.Flags) then begin
if Params.IdentifierTool.IsPCharInSrc(Params.Identifier) then
Params.IdentifierTool.MoveCursorToCleanPos(Params.Identifier);
Params.IdentifierTool.RaiseException('Identifier not found '
+'"'+GetIdentifier(Params.Identifier)+'"');
end;
end;
begin begin
Result:=false; Result:=false;
ContextNode:=Params.ContextNode; ContextNode:=Params.ContextNode;
@ -977,22 +994,32 @@ begin
try try
LastNodeCache:=nil; LastNodeCache:=nil;
LastCacheEntry:=nil; LastCacheEntry:=nil;
repeat NodeCacheEntryFlags:=[];
if fdfSearchInParentNodes in Params.Flags then
Include(NodeCacheEntryFlags,ncefSearchedInParents);
if fdfSearchInAncestors in Params.Flags then
Include(NodeCacheEntryFlags,ncefSearchedInAncestors);
{$IFDEF ShowTriedContexts} {$IFDEF ShowTriedContexts}
writeln('[TFindDeclarationTool.FindIdentifierInContext] A Ident=', writeln('[TFindDeclarationTool.FindIdentifierInContext] A Ident=',
'"',GetIdentifier(Params.Identifier),'"', '"',GetIdentifier(Params.Identifier),'"',
' Context="',ContextNode.DescAsString,'" "',copy(Src,ContextNode.StartPos,20),'"', ' Context="',ContextNode.DescAsString,'" "',copy(Src,ContextNode.StartPos,20),'"',
' Flags=[',FindDeclarationFlagsAsString(Params.Flags),']' ' Flags=[',FindDeclarationFlagsAsString(Params.Flags),']'
); );
if (ContextNode.Desc=ctnClass) then {$ENDIF}
writeln(' ContextNode.LastChild=',ContextNode.LastChild<>nil); repeat
{$IFDEF ShowTriedIdentifiers}
writeln('[TFindDeclarationTool.FindIdentifierInContext] A Ident=',
'"',GetIdentifier(Params.Identifier),'"',
' Context="',ContextNode.DescAsString,'" "',copy(Src,ContextNode.StartPos,20),'"',
' Flags=[',FindDeclarationFlagsAsString(Params.Flags),']'
);
{$ENDIF} {$ENDIF}
// search identifier in current context // search identifier in current context
LastContextNode:=ContextNode; LastContextNode:=ContextNode;
if not (fdfIgnoreCurContextNode in Params.Flags) then begin if not (fdfIgnoreCurContextNode in Params.Flags) then begin
// search in cache // search in cache
if FindInNodeCache then begin if FindInNodeCache then begin
Result:=(Params.NewNode<>nil); SetResultBeforeExit(Params.NewNode<>nil);
exit; exit;
end; end;
if FirstSearchedNode=nil then FirstSearchedNode:=ContextNode; if FirstSearchedNode=nil then FirstSearchedNode:=ContextNode;
@ -1065,7 +1092,7 @@ writeln(' Definition Identifier found="',GetIdentifier(Params.Identifier),'"');
end else begin end else begin
IdentifierFoundResult:=DoOnIdentifierFound(Params,ContextNode); IdentifierFoundResult:=DoOnIdentifierFound(Params,ContextNode);
if IdentifierFoundResult in [ifrAbortSearch,ifrSuccess] then begin if IdentifierFoundResult in [ifrAbortSearch,ifrSuccess] then begin
Result:=(IdentifierFoundResult=ifrSuccess); SetResultBeforeExit(IdentifierFoundResult=ifrSuccess);
exit; exit;
end; end;
end; end;
@ -1080,7 +1107,7 @@ writeln(' Definition Identifier found="',GetIdentifier(Params.Identifier),'"');
IdentifierFoundResult:= IdentifierFoundResult:=
FindIdentifierInProcContext(ContextNode,Params); FindIdentifierInProcContext(ContextNode,Params);
if IdentifierFoundResult in [ifrAbortSearch,ifrSuccess] then begin if IdentifierFoundResult in [ifrAbortSearch,ifrSuccess] then begin
Result:=(IdentifierFoundResult=ifrSuccess); SetResultBeforeExit(IdentifierFoundResult=ifrSuccess);
exit; exit;
end; end;
end; end;
@ -1111,7 +1138,7 @@ writeln(' Source Name Identifier found="',GetIdentifier(Params.Identifier),'"')
end else begin end else begin
IdentifierFoundResult:=DoOnIdentifierFound(Params,ContextNode); IdentifierFoundResult:=DoOnIdentifierFound(Params,ContextNode);
if IdentifierFoundResult in [ifrAbortSearch,ifrSuccess] then begin if IdentifierFoundResult in [ifrAbortSearch,ifrSuccess] then begin
Result:=(IdentifierFoundResult=ifrSuccess); SetResultBeforeExit(IdentifierFoundResult=ifrSuccess);
exit; exit;
end; end;
end; end;
@ -1148,7 +1175,7 @@ writeln(' Property Identifier found="',GetIdentifier(Params.Identifier),'"');
end else begin end else begin
IdentifierFoundResult:=DoOnIdentifierFound(Params,ContextNode); IdentifierFoundResult:=DoOnIdentifierFound(Params,ContextNode);
if IdentifierFoundResult in [ifrAbortSearch,ifrSuccess] then begin if IdentifierFoundResult in [ifrAbortSearch,ifrSuccess] then begin
Result:=(IdentifierFoundResult=ifrSuccess); SetResultBeforeExit(IdentifierFoundResult=ifrSuccess);
exit; exit;
end; end;
end; end;
@ -1170,7 +1197,7 @@ writeln(' Property Identifier found="',GetIdentifier(Params.Identifier),'"');
begin begin
// pointer types can be forward definitions // pointer types can be forward definitions
Params.ContextNode:=ContextNode.Parent; Params.ContextNode:=ContextNode.Parent;
Result:=FindForwardIdentifier(Params,IsForward); SetResultBeforeExit(FindForwardIdentifier(Params,IsForward));
exit; exit;
end; end;
@ -1195,14 +1222,15 @@ writeln('[TFindDeclarationTool.FindIdentifierInContext] IgnoreCurContext');
{$IFDEF ShowTriedContexts} {$IFDEF ShowTriedContexts}
writeln('[TFindDeclarationTool.FindIdentifierInContext] no prior node accessible ContextNode=',ContextNode.DescAsString); writeln('[TFindDeclarationTool.FindIdentifierInContext] no prior node accessible ContextNode=',ContextNode.DescAsString);
{$ENDIF} {$ENDIF}
exit; ContextNode:=nil;
break;
end; end;
end; end;
end; end;
repeat repeat
// search for prior node // search for prior node
{$IFDEF ShowTriedContexts} {$IFDEF ShowTriedIdentifiers}
//writeln('[TFindDeclarationTool.FindIdentifierInContext] Searching prior node of ',ContextNode.DescAsString); //writeln('[TFindDeclarationTool.FindIdentifierInContext] Searching prior node of ',ContextNode.DescAsString);
{$ENDIF} {$ENDIF}
LastSearchedNode:=ContextNode; LastSearchedNode:=ContextNode;
@ -1230,7 +1258,7 @@ writeln('[TFindDeclarationTool.FindIdentifierInContext] no prior node accessible
ContextNode:=ContextNode.PriorBrother ContextNode:=ContextNode.PriorBrother
else else
ContextNode:=ContextNode.NextBrother; ContextNode:=ContextNode.NextBrother;
{$IFDEF ShowTriedContexts} {$IFDEF ShowTriedIdentifiers}
writeln('[TFindDeclarationTool.FindIdentifierInContext] Searching in PriorBrother ContextNode=',ContextNode.DescAsString); writeln('[TFindDeclarationTool.FindIdentifierInContext] Searching in PriorBrother ContextNode=',ContextNode.DescAsString);
{$ENDIF} {$ENDIF}
// it is not always allowed to search in every node on the same lvl: // it is not always allowed to search in every node on the same lvl:
@ -1250,7 +1278,7 @@ writeln('[TFindDeclarationTool.FindIdentifierInContext] Searching in PriorBrothe
begin begin
// search next in parent // search next in parent
ContextNode:=ContextNode.Parent; ContextNode:=ContextNode.Parent;
{$IFDEF ShowTriedContexts} {$IFDEF ShowTriedIdentifiers}
writeln('[TFindDeclarationTool.FindIdentifierInContext] Searching in Parent ContextNode=',ContextNode.DescAsString); writeln('[TFindDeclarationTool.FindIdentifierInContext] Searching in Parent ContextNode=',ContextNode.DescAsString);
{$ENDIF} {$ENDIF}
case ContextNode.Desc of case ContextNode.Desc of
@ -1290,7 +1318,7 @@ writeln('[TFindDeclarationTool.FindIdentifierInContext] Searching in Parent Con
finally finally
if Result and (not (fdfDoNotCache in Params.NewFlags)) if Result and (not (fdfDoNotCache in Params.NewFlags))
and (FirstSearchedNode<>nil) then begin and (FirstSearchedNode<>nil) then begin
// add result to caches // cache result
AddResultToNodeCaches(Params.Identifier,FirstSearchedNode,ContextNode, AddResultToNodeCaches(Params.Identifier,FirstSearchedNode,ContextNode,
fdfSearchForward in Params.Flags,Params,SearchRangeFlags); fdfSearchForward in Params.Flags,Params,SearchRangeFlags);
end; end;
@ -1302,12 +1330,7 @@ writeln('[TFindDeclarationTool.FindIdentifierInContext] Searching in Parent Con
fdfSearchForward in Params.Flags,nil,SearchRangeFlags); fdfSearchForward in Params.Flags,nil,SearchRangeFlags);
end; end;
if fdfExceptionOnNotFound in Params.Flags then begin SetResultBeforeExit(false);
if Params.IdentifierTool.IsPCharInSrc(Params.Identifier) then
Params.IdentifierTool.MoveCursorToCleanPos(Params.Identifier);
Params.IdentifierTool.RaiseException('Identifier not found '
+'"'+GetIdentifier(Params.Identifier)+'"');
end;
end; end;
function TFindDeclarationTool.FindEnumInContext( function TFindDeclarationTool.FindEnumInContext(
@ -1535,6 +1558,22 @@ writeln('');
end; end;
end; end;
end; end;
{ ToDo: check, if this is needed for Delphi:
if (NextAtomType in [atSpace])
and CompareSrcIdentifier(CurAtom.StartPos,'FREE')
and ((Result.Node.Desc=ctnClass) or NodeIsInAMethod(Result.Node)) then
begin
// FREE calls the destructor of an object
Params.Save(OldInput);
Params.SetIdentifier(Self,'DESTRUCTOR',nil);
Exclude(Params.Flags,fdfExceptionOnNotFound);
if Result.Tool.FindIdentifierInContext(Params) then begin
Result:=CreateFindContext(Params);
exit;
end;
Params.Load(OldInput);
end;}
// find sub identifier // find sub identifier
Params.Save(OldInput); Params.Save(OldInput);
try try
@ -2016,10 +2055,9 @@ var
NameAtom: TAtomPosition; NameAtom: TAtomPosition;
begin begin
Result:=ifrProceedSearch; Result:=ifrProceedSearch;
// if proc is a method, search in class // if proc is a method body, search in class
// -> find class name // -> find class name
MoveCursorToNodeStart(ProcContextNode); MoveCursorToNodeStart(ProcContextNode.FirstChild);
ReadNextAtom; // read keyword
ReadNextAtom; // read name ReadNextAtom; // read name
NameAtom:=CurPos; NameAtom:=CurPos;
ReadNextAtom; ReadNextAtom;
@ -2722,7 +2760,7 @@ writeln(DebugPrefix,'TFindDeclarationTool.FindIdentifierInInterface',
CacheEntry:=FInterfaceIdentifierCache.FindIdentifier(Params.Identifier); CacheEntry:=FInterfaceIdentifierCache.FindIdentifier(Params.Identifier);
if CacheEntry<>nil then begin if CacheEntry<>nil then begin
// identifier in cache found // identifier in cache found
{$IFDEF ShowCachedIdentifiers} {$IFDEF ShowInterfaceCache}
writeln('[TFindDeclarationTool.FindIdentifierInInterface] Ident already in cache:', writeln('[TFindDeclarationTool.FindIdentifierInInterface] Ident already in cache:',
' Exists=',CacheEntry^.Node<>nil); ' Exists=',CacheEntry^.Node<>nil);
{$ENDIF} {$ENDIF}
@ -2864,6 +2902,25 @@ writeln('[TFindDeclarationTool.FindIdentifierInUsedUnit] ',
end; end;
end; end;
function TFindDeclarationTool.NodeIsInAMethod(Node: TCodeTreeNode): boolean;
begin
Result:=false;
while (Node<>nil) do begin
if (Node.Desc=ctnProcedure) then begin
// ToDo: ppu, ppw, dcu
MoveCursorToNodeStart(Node.FirstChild); // ctnProcedureHead
ReadNextAtom;
if not AtomIsIdentifier(false) then continue;
ReadNextAtom;
if not AtomIsChar('.') then continue;
Result:=true;
exit;
end;
end;
end;
function TFindDeclarationTool.FindIdentifierInHiddenUsedUnits( function TFindDeclarationTool.FindIdentifierInHiddenUsedUnits(
Params: TFindDeclarationParams): boolean; Params: TFindDeclarationParams): boolean;
const const
@ -3882,22 +3939,28 @@ var Node: TCodeTreeNode;
NewCleanPos: integer; NewCleanPos: integer;
begin begin
{$IFDEF ShowNodeCache} {$IFDEF ShowNodeCache}
//if CompareSrcIdentifiers(Identifier,'TDefineTree') then writeln('=================================');
write('TFindDeclarationTool.AddResultToNodeCaches ', write('TFindDeclarationTool.AddResultToNodeCaches ',
' Ident=',GetIdentifier(Identifier), ' Ident=',GetIdentifier(Identifier));
' StartNode=',StartNode.DescAsString,'="',copy(Src,StartNode.StartPos-10,10),'|',copy(Src,StartNode.StartPos,15),'"'); write(' SearchedForward=',SearchedForward);
write(' Flags=[');
if ncefSearchedInParents in SearchRangeFlags then write('Parents');
if ncefSearchedInAncestors in SearchRangeFlags then write(',Ancestors');
writeln(']');
write(' StartNode=',StartNode.DescAsString,'="',copy(Src,StartNode.StartPos-10,10),'|',copy(Src,StartNode.StartPos,15),'"');
if EndNode<>nil then if EndNode<>nil then
write(' EndNode=',EndNode.DescAsString,'="',copy(Src,EndNode.StartPos,25),'"') write(' EndNode=',EndNode.DescAsString,'="',copy(Src,EndNode.StartPos,25),'"')
else else
write(' EndNode=nil'); write(' EndNode=nil');
write(' SearchedForward=',SearchedForward);
writeln(''); writeln('');
writeln(' Self=',MainFilename); writeln(' Self=',MainFilename);
if Params<>nil then begin if Params<>nil then begin
writeln(' NewNode=',Params.NewNode.DescAsString, writeln(' NewNode=',Params.NewNode.DescAsString,
' NewTool=',Params.NewCodeTool.MainFilename); ' NewTool=',Params.NewCodeTool.MainFilename);
end else begin end else begin
writeln(' NOT FOUND'); writeln(' NOT FOUND');
end; end;
//if CompareSrcIdentifiers(Identifier,'TDefineTree') then writeln('=================================');
{$ENDIF} {$ENDIF}
Node:=StartNode; Node:=StartNode;
LastNodeCache:=nil; LastNodeCache:=nil;

View File

@ -35,7 +35,7 @@ interface
uses uses
Classes, SysUtils, LCLLinux, Forms, Controls, Buttons, StdCtrls, ComCtrls, Classes, SysUtils, LCLLinux, Forms, Controls, Buttons, StdCtrls, ComCtrls,
ExtCtrls, Menus, LResources, Graphics, Dialogs, ImgList, SynEdit, ExtCtrls, Menus, LResources, Graphics, Dialogs, ImgList, SynEdit, XMLCfg,
DefineTemplates, CodeToolManager, CodeToolsOptions; DefineTemplates, CodeToolManager, CodeToolsOptions;
type type
@ -81,6 +81,19 @@ type
InsertAsChildElseIfMenuItem: TMenuItem; InsertAsChildElseIfMenuItem: TMenuItem;
InsertAsChildElseMenuItem: TMenuItem; InsertAsChildElseMenuItem: TMenuItem;
DeleteNodeMenuItem: TMenuItem; DeleteNodeMenuItem: TMenuItem;
ConvertActionMenuItem: TMenuItem;
ConvertActionToDefineMenuItem: TMenuItem;
ConvertActionToDefineRecurseMenuItem: TMenuItem;
ConvertActionToUndefineMenuItem: TMenuItem;
ConvertActionToUndefineRecurseMenuItem: TMenuItem;
ConvertActionToUndefineAllMenuItem: TMenuItem;
ConvertActionToBlockMenuItem: TMenuItem;
ConvertActionToDirectoryMenuItem: TMenuItem;
ConvertActionToIfMenuItem: TMenuItem;
ConvertActionToIfDefMenuItem: TMenuItem;
ConvertActionToIfNotDefMenuItem: TMenuItem;
ConvertActionToElseIfMenuItem: TMenuItem;
ConvertActionToElseMenuItem: TMenuItem;
CopyToClipbrdMenuItem: TMenuItem; CopyToClipbrdMenuItem: TMenuItem;
PasteFromClipbrdMenuItem: TMenuItem; PasteFromClipbrdMenuItem: TMenuItem;
@ -137,6 +150,7 @@ type
procedure MoveNodeLvlUpMenuItemClick(Sender: TObject); procedure MoveNodeLvlUpMenuItemClick(Sender: TObject);
procedure MoveNodeLvlDownMenuItemClick(Sender: TObject); procedure MoveNodeLvlDownMenuItemClick(Sender: TObject);
procedure DeleteNodeMenuItemClick(Sender: TObject); procedure DeleteNodeMenuItemClick(Sender: TObject);
procedure ConvertActionMenuItemClick(Sender: TObject);
private private
FDefineTree: TDefineTree; FDefineTree: TDefineTree;
FLastSelectedNode: TTreeNode; FLastSelectedNode: TTreeNode;
@ -186,8 +200,37 @@ end;
{ TCodeToolsDefinesEditor } { TCodeToolsDefinesEditor }
procedure TCodeToolsDefinesEditor.SaveAndExitMenuItemClick(Sender: TObject); procedure TCodeToolsDefinesEditor.SaveAndExitMenuItemClick(Sender: TObject);
var XMLConfig: TXMLConfig;
t: TDefineTree;
begin begin
ModalResult:=mrOk; SaveSelectedValues(DefineTreeView.Selected);
FLastSelectedNode:=nil;
t:=TDefineTree.Create;
t.Assign(DefineTree);
writeln(' WWW TCodeToolsDefinesEditor.SaveAndExitMenuItemClick 0 ',t.IsEqual(DefineTree),' Consistency=',ConsistencyCheck);
XMLConfig:=TXMLConfig.Create('/home/mattias/pascal/defines.xml');
writeln(' WWW TCodeToolsDefinesEditor.SaveAndExitMenuItemClick A');
DefineTree.SaveToXMLConfig(XMLConfig,'Globals/',dtspGlobals);
writeln(' WWW TCodeToolsDefinesEditor.SaveAndExitMenuItemClick B');
DefineTree.SaveToXMLConfig(XMLConfig,'Project/',dtspProjectSpecific);
XMLConfig.Flush;
writeln(' WWW TCodeToolsDefinesEditor.SaveAndExitMenuItemClick C ');
DefineTree.LoadFromXMLConfig(XMLConfig,'Globals/',dtlpGlobals,'Global');
writeln(' WWW TCodeToolsDefinesEditor.SaveAndExitMenuItemClick C ');
DefineTree.LoadFromXMLConfig(XMLConfig,'Project/',dtlpProjectSpecific,'Project');
writeln(' WWW TCodeToolsDefinesEditor.SaveAndExitMenuItemClick D ',t.IsEqual(DefineTree),' Consistency=',ConsistencyCheck);
RebuildDefineTreeView;
writeln(' WWW TCodeToolsDefinesEditor.SaveAndExitMenuItemClick END',' Consistency=',ConsistencyCheck);
t.Free;
XMLConfig.Free;
//ModalResult:=mrOk;
end; end;
procedure TCodeToolsDefinesEditor.DontSaveAndExitMenuItemClick(Sender: TObject); procedure TCodeToolsDefinesEditor.DontSaveAndExitMenuItemClick(Sender: TObject);
@ -499,6 +542,37 @@ writeln(' AAA1 ',ConsistencyCheck);
writeln(' AAA2 ',ConsistencyCheck); writeln(' AAA2 ',ConsistencyCheck);
end; end;
procedure TCodeToolsDefinesEditor.ConvertActionMenuItemClick(Sender: TObject);
var
NewAction: TDefineAction;
SelTreeNode: TTreeNode;
SelDefNode: TDefineTemplate;
begin
SelTreeNode:=DefineTreeView.Selected;
if SelTreeNode=nil then exit;
SelDefNode:=TDefineTemplate(SelTreeNode.Data);
if (SelDefNode.IsAutoGenerated) then begin
MessageDlg('Node is readonly','Auto generated nodes can not be edited.',
mtInformation,[mbCancel],0);
exit;
end;
if Sender=ConvertActionToDefineMenuItem then NewAction:=da_Define
else if Sender=ConvertActionToDefineRecurseMenuItem then NewAction:=da_DefineRecurse
else if Sender=ConvertActionToUndefineMenuItem then NewAction:=da_Undefine
else if Sender=ConvertActionToUndefineRecurseMenuItem then NewAction:=da_UndefineRecurse
else if Sender=ConvertActionToUndefineAllMenuItem then NewAction:=da_UndefineAll
else if Sender=ConvertActionToBlockMenuItem then NewAction:=da_Block
else if Sender=ConvertActionToDirectoryMenuItem then NewAction:=da_Directory
else if Sender=ConvertActionToIfMenuItem then NewAction:=da_If
else if Sender=ConvertActionToIfDefMenuItem then NewAction:=da_IfDef
else if Sender=ConvertActionToIfNotDefMenuItem then NewAction:=da_IfNDef
else if Sender=ConvertActionToElseIfMenuItem then NewAction:=da_ElseIf
else if Sender=ConvertActionToElseMenuItem then NewAction:=da_Else;
SelDefNode.Action:=NewAction;
SetNodeImages(SelTreeNode,false);
SetTypeLabel;
end;
procedure TCodeToolsDefinesEditor.ProjectSpecificCheckBoxClick(Sender: TObject); procedure TCodeToolsDefinesEditor.ProjectSpecificCheckBoxClick(Sender: TObject);
var var
SelTreeNode: TTreeNode; SelTreeNode: TTreeNode;
@ -616,15 +690,22 @@ begin
MoveNodeLvlDownMenuItem.OnClick:=@MoveNodeLvlDownMenuItemClick; MoveNodeLvlDownMenuItem.OnClick:=@MoveNodeLvlDownMenuItemClick;
EditMenuItem.Add(CreateSeperator); EditMenuItem.Add(CreateSeperator);
AddMenuItem(InsertBehindMenuItem,'InsertBehindMenuItem','Insert node below', AddMenuItem(InsertBehindMenuItem,'InsertBehindMenuItem','Insert node below',
EditMenuItem); EditMenuItem);
AddMenuItem(InsertAsChildMenuItem,'InsertAsChildMenuItem','Insert node as child', AddMenuItem(InsertAsChildMenuItem,'InsertAsChildMenuItem','Insert node as child',
EditMenuItem); EditMenuItem);
EditMenuItem.Add(CreateSeperator); EditMenuItem.Add(CreateSeperator);
AddMenuItem(DeleteNodeMenuItem,'DeleteNodeMenuItem','Delete node', AddMenuItem(DeleteNodeMenuItem,'DeleteNodeMenuItem','Delete node',
EditMenuItem); EditMenuItem);
DeleteNodeMenuItem.OnClick:=@DeleteNodeMenuItemClick; DeleteNodeMenuItem.OnClick:=@DeleteNodeMenuItemClick;
AddMenuItem(ConvertActionMenuItem,'ConvertActionMenuItem','Convert node',
EditMenuItem);
{ EditMenuItem.Add(CreateSeperator); { EditMenuItem.Add(CreateSeperator);
AddMenuItem(CopyToClipbrdMenuItem,'CopyToClipbrdMenuItem','Copy to clipboard', AddMenuItem(CopyToClipbrdMenuItem,'CopyToClipbrdMenuItem','Copy to clipboard',
EditMenuItem); EditMenuItem);
@ -702,6 +783,42 @@ begin
for i:=0 to InsertAsChildMenuItem.Count-1 do for i:=0 to InsertAsChildMenuItem.Count-1 do
if InsertAsChildMenuItem[i].Caption<>'-' then if InsertAsChildMenuItem[i].Caption<>'-' then
InsertAsChildMenuItem[i].OnClick:=@InsertNodeMenuItemClick; InsertAsChildMenuItem[i].OnClick:=@InsertNodeMenuItemClick;
// convert node sub menu
AddMenuItem(ConvertActionToDefineMenuItem,'ConvertActionToDefineMenuItem','Define',
ConvertActionMenuItem);
AddMenuItem(ConvertActionToDefineRecurseMenuItem,
'ConvertActionToDefineRecurseMenuItem','Define Recurse',
ConvertActionMenuItem);
AddMenuItem(ConvertActionToUndefineMenuItem,
'ConvertActionToUndefineMenuItem','Undefine',
ConvertActionMenuItem);
AddMenuItem(ConvertActionToUndefineRecurseMenuItem,
'ConvertActionToUndefineRecurseMenuItem','Undefine Recurse',
ConvertActionMenuItem);
AddMenuItem(ConvertActionToUndefineAllMenuItem,
'ConvertActionToUndefineAllMenuItem','Undefine All',
ConvertActionMenuItem);
ConvertActionMenuItem.Add(CreateSeperator);
AddMenuItem(ConvertActionToBlockMenuItem,'ConvertActionToBlockMenuItem','Block',
ConvertActionMenuItem);
AddMenuItem(ConvertActionToDirectoryMenuItem,
'ConvertActionToDirectoryMenuItem','Directory',
ConvertActionMenuItem);
ConvertActionMenuItem.Add(CreateSeperator);
AddMenuItem(ConvertActionToIfMenuItem,'ConvertActionToIfMenuItem','If',
ConvertActionMenuItem);
AddMenuItem(ConvertActionToIfDefMenuItem,'ConvertActionToIfDefMenuItem','IfDef',
ConvertActionMenuItem);
AddMenuItem(ConvertActionToIfNotDefMenuItem,'ConvertActionToIfNotDefMenuItem','IfNDef',
ConvertActionMenuItem);
AddMenuItem(ConvertActionToElseIfMenuItem,'ConvertActionToElseIfMenuItem','ElseIf',
ConvertActionMenuItem);
AddMenuItem(ConvertActionToElseMenuItem,'ConvertActionToElseMenuItem','Else',
ConvertActionMenuItem);
for i:=0 to ConvertActionMenuItem.Count-1 do
if ConvertActionMenuItem[i].Caption<>'-' then
ConvertActionMenuItem[i].OnClick:=@ConvertActionMenuItemClick;
// tools // tools
{ AddMenuItem(ToolsMenuItem,'ToolsMenuItem','Tools',nil); { AddMenuItem(ToolsMenuItem,'ToolsMenuItem','Tools',nil);
@ -1106,11 +1223,11 @@ function TCodeToolsDefinesEditor.ConsistencyCheck: integer;
writeln('ATreeNode.GetNextSibling.Next=',DummyDefNode.Name) writeln('ATreeNode.GetNextSibling.Next=',DummyDefNode.Name)
else else
writeln('ATreeNode.GetNextSibling.Next=nil'); writeln('ATreeNode.GetNextSibling.Next=nil');
writeln('============================================='); {writeln('=============================================');
DefineTreeView.WriteDebugReport('TV ',true); DefineTreeView.WriteDebugReport('TV ',true);
writeln('============================================='); writeln('=============================================');
DefineTree.WriteDebugReport; DefineTree.WriteDebugReport;
writeln('============================================='); writeln('=============================================');}
Result:=-3; exit; Result:=-3; exit;
end; end;
if (ATreeNode.GetFirstChild<>nil) if (ATreeNode.GetFirstChild<>nil)