mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-25 09:59:33 +02:00
cody: dictionary: parse unit
git-svn-id: trunk@33492 -
This commit is contained in:
parent
a4621e4039
commit
7c6f076695
@ -79,7 +79,7 @@ type
|
||||
procedure ConsistencyCheck;
|
||||
property Tool: TPascalParserTool read FTool;
|
||||
property Complete: boolean read FComplete write SetComplete;
|
||||
property Items: TAVLTree read FItems;
|
||||
property Items: TAVLTree read FItems; // Tree of PInterfaceIdentCacheEntry
|
||||
function CalcMemSize: PtrUInt;
|
||||
end;
|
||||
|
||||
|
@ -30,7 +30,8 @@ unit unitdictionary;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, AVL_Tree, BasicCodeTools, FileProcs;
|
||||
Classes, SysUtils, AVL_Tree, BasicCodeTools, FileProcs,
|
||||
FindDeclarationCache, CodeToolManager;
|
||||
|
||||
type
|
||||
TUDIdentifier = class;
|
||||
@ -62,6 +63,7 @@ type
|
||||
destructor Destroy; override;
|
||||
function AddUnit(NewUnit: TUDUnit): TUDUnit; overload;
|
||||
function AddUnit(const aName, aFilename: string): TUDUnit; overload;
|
||||
procedure RemoveUnit(TheUnit: TUDUnit);
|
||||
end;
|
||||
|
||||
{ TUDUnit }
|
||||
@ -69,11 +71,14 @@ type
|
||||
TUDUnit = class(TUDFileItem)
|
||||
public
|
||||
FileAge: longint;
|
||||
FirstIdentifier: TUDIdentifier;
|
||||
FirstIdentifier, LastIdentifier: TUDIdentifier;
|
||||
UnitGroups: TAVLTree; // tree of TUDUnitGroup sorted with CompareIDItems
|
||||
constructor Create(const aName, aFilename: string);
|
||||
destructor Destroy; override;
|
||||
function AddIdentifier(aName: PChar): TUDIdentifier;
|
||||
function AddIdentifier(Item: TUDIdentifier): TUDIdentifier;
|
||||
procedure ClearIdentifiers;
|
||||
function IsInGroup(Group: TUDUnitGroup): boolean;
|
||||
function GetDictionary: TUnitDictionary;
|
||||
end;
|
||||
|
||||
{ TUDIdentifier }
|
||||
@ -90,17 +95,22 @@ type
|
||||
|
||||
TUnitDictionary = class
|
||||
private
|
||||
FDefaultGroup: TUDUnitGroup;
|
||||
FIdentifiers: TAVLTree; // tree of TUDIdentifier sorted with CompareIDItems
|
||||
FUnitsByName: TAVLTree; // tree of TUDUnit sorted with CompareIDItems
|
||||
FUnitsByFilename: TAVLTree; // tree of TUDUnit sorted with CompareIDFileItems
|
||||
FUnitGroupsByName: TAVLTree; // tree of TUDUnitGroup sorted with CompareIDItems
|
||||
FUnitGroupsByFilename: TAVLTree; // tree of TUDUnitGroup sorted with CompareIDFileItems
|
||||
procedure RemoveIdentifier(Item: TUDIdentifier);
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
procedure Clear;
|
||||
procedure Clear(CreateDefaults: boolean = true);
|
||||
function AddUnitGroup(Group: TUDUnitGroup): TUDUnitGroup; overload;
|
||||
function AddUnitGroup(const aName, aFilename: string): TUDUnitGroup; overload;
|
||||
property DefaultGroup: TUDUnitGroup read FDefaultGroup;
|
||||
procedure ParseUnit(Tool: TCodeTool; Group: TUDUnitGroup = nil);
|
||||
function FindUnitWithFilename(const aFilename: string): TUDUnit;
|
||||
end;
|
||||
|
||||
function CompareNameWithIDItem(NamePChar, Item: Pointer): integer;
|
||||
@ -184,9 +194,42 @@ begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TUDUnit.AddIdentifier(aName: PChar): TUDIdentifier;
|
||||
function TUDUnit.AddIdentifier(Item: TUDIdentifier): TUDIdentifier;
|
||||
begin
|
||||
Result:=TUDIdentifier.Create(aName);
|
||||
Result:=Item;
|
||||
Result.DUnit:=Self;
|
||||
if LastIdentifier<>nil then
|
||||
LastIdentifier.NextInUnit:=Result
|
||||
else
|
||||
FirstIdentifier:=Result;
|
||||
Result.NextInUnit:=nil;
|
||||
LastIdentifier:=Result;
|
||||
end;
|
||||
|
||||
procedure TUDUnit.ClearIdentifiers;
|
||||
var
|
||||
Item: TUDIdentifier;
|
||||
Dictionary: TUnitDictionary;
|
||||
begin
|
||||
Dictionary:=GetDictionary;
|
||||
while FirstIdentifier<>nil do begin
|
||||
Item:=FirstIdentifier;
|
||||
FirstIdentifier:=Item.NextInUnit;
|
||||
Item.NextInUnit:=nil;
|
||||
Dictionary.RemoveIdentifier(Item);
|
||||
Item.Free;
|
||||
end;
|
||||
LastIdentifier:=nil;
|
||||
end;
|
||||
|
||||
function TUDUnit.IsInGroup(Group: TUDUnitGroup): boolean;
|
||||
begin
|
||||
Result:=UnitGroups.FindPointer(Group)<>nil;
|
||||
end;
|
||||
|
||||
function TUDUnit.GetDictionary: TUnitDictionary;
|
||||
begin
|
||||
Result:=TUDUnitGroup(UnitGroups.Root.Data).Dictionary;
|
||||
end;
|
||||
|
||||
{ TUDUnitGroup }
|
||||
@ -208,7 +251,9 @@ end;
|
||||
function TUDUnitGroup.AddUnit(NewUnit: TUDUnit): TUDUnit;
|
||||
begin
|
||||
Result:=NewUnit;
|
||||
if Units.FindPointer(NewUnit)<>nil then exit;
|
||||
Units.Add(Result);
|
||||
Result.UnitGroups.Add(Self);
|
||||
end;
|
||||
|
||||
function TUDUnitGroup.AddUnit(const aName, aFilename: string): TUDUnit;
|
||||
@ -216,6 +261,12 @@ begin
|
||||
Result:=AddUnit(TUDUnit.Create(aName,aFilename));
|
||||
end;
|
||||
|
||||
procedure TUDUnitGroup.RemoveUnit(TheUnit: TUDUnit);
|
||||
begin
|
||||
Units.RemovePointer(TheUnit);
|
||||
TheUnit.UnitGroups.RemovePointer(Self);
|
||||
end;
|
||||
|
||||
{ TUDFileItem }
|
||||
|
||||
constructor TUDFileItem.Create(const aName, aFilename: string);
|
||||
@ -226,6 +277,11 @@ end;
|
||||
|
||||
{ TUnitDictionary }
|
||||
|
||||
procedure TUnitDictionary.RemoveIdentifier(Item: TUDIdentifier);
|
||||
begin
|
||||
FIdentifiers.RemovePointer(Item);
|
||||
end;
|
||||
|
||||
constructor TUnitDictionary.Create;
|
||||
begin
|
||||
FIdentifiers:=TAVLTree.Create(@CompareIDItems);
|
||||
@ -233,11 +289,12 @@ begin
|
||||
FUnitsByFilename:=TAVLTree.Create(@CompareIDFileItems);
|
||||
FUnitGroupsByName:=TAVLTree.Create(@CompareIDItems);
|
||||
FUnitGroupsByFilename:=TAVLTree.Create(@CompareIDFileItems);
|
||||
FDefaultGroup:=AddUnitGroup('','');
|
||||
end;
|
||||
|
||||
destructor TUnitDictionary.Destroy;
|
||||
begin
|
||||
Clear;
|
||||
Clear(false);
|
||||
FreeAndNil(FIdentifiers);
|
||||
FreeAndNil(FUnitsByName);
|
||||
FreeAndNil(FUnitsByFilename);
|
||||
@ -246,13 +303,16 @@ begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TUnitDictionary.Clear;
|
||||
procedure TUnitDictionary.Clear(CreateDefaults: boolean);
|
||||
begin
|
||||
FDefaultGroup:=nil;
|
||||
FUnitGroupsByFilename.Clear;
|
||||
FUnitGroupsByName.FreeAndClear;
|
||||
FUnitsByFilename.Clear;
|
||||
FUnitsByName.FreeAndClear;
|
||||
FIdentifiers.FreeAndClear;
|
||||
if CreateDefaults then
|
||||
FDefaultGroup:=AddUnitGroup('','');
|
||||
end;
|
||||
|
||||
function TUnitDictionary.AddUnitGroup(Group: TUDUnitGroup): TUDUnitGroup;
|
||||
@ -271,5 +331,102 @@ begin
|
||||
Result:=AddUnitGroup(TUDUnitGroup.Create(aName,aFilename));
|
||||
end;
|
||||
|
||||
procedure TUnitDictionary.ParseUnit(Tool: TCodeTool; Group: TUDUnitGroup);
|
||||
var
|
||||
SrcTree: TAVLTree;
|
||||
AVLNode: TAVLTreeNode;
|
||||
Item: PInterfaceIdentCacheEntry;
|
||||
UnitFilename: String;
|
||||
CurUnit: TUDUnit;
|
||||
NiceName: String;
|
||||
SrcName: String;
|
||||
IdentifierItem: TUDIdentifier;
|
||||
Changed: Boolean;
|
||||
begin
|
||||
if Tool=nil then exit;
|
||||
if Group=nil then
|
||||
Group:=DefaultGroup;
|
||||
// parse unit
|
||||
Tool.BuildInterfaceIdentifierCache(true);
|
||||
|
||||
// get unit name from source
|
||||
UnitFilename:=Tool.MainFilename;
|
||||
NiceName:=ExtractFileNameOnly(UnitFilename);
|
||||
if (LowerCase(NiceName)=NiceName)
|
||||
or (UpperCase(NiceName)=NiceName) then begin
|
||||
SrcName:=Tool.GetSourceName(false);
|
||||
if CompareDottedIdentifiers(PChar(SrcName),PChar(NiceName))=0 then
|
||||
NiceName:=SrcName;
|
||||
end;
|
||||
|
||||
// find/create unit
|
||||
CurUnit:=FindUnitWithFilename(UnitFilename);
|
||||
if CurUnit<>nil then begin
|
||||
// old unit
|
||||
if (Group<>DefaultGroup) then begin
|
||||
if CurUnit.IsInGroup(DefaultGroup) then begin
|
||||
// move from no group to some group
|
||||
DefaultGroup.RemoveUnit(CurUnit);
|
||||
end;
|
||||
Group.AddUnit(CurUnit);
|
||||
end;
|
||||
// update name
|
||||
if CurUnit.Name<>NiceName then
|
||||
CurUnit.Name:=NiceName;
|
||||
end else begin
|
||||
// new unit
|
||||
CurUnit:=Group.AddUnit(NiceName,UnitFilename);
|
||||
FUnitsByName.Add(CurUnit);
|
||||
FUnitsByFilename.Add(CurUnit);
|
||||
end;
|
||||
|
||||
SrcTree:=Tool.InterfaceIdentifierCache.Items;
|
||||
// check if something changed
|
||||
AVLNode:=SrcTree.FindLowest;
|
||||
Changed:=false;
|
||||
IdentifierItem:=CurUnit.FirstIdentifier;
|
||||
while AVLNode<>nil do begin
|
||||
Item:=PInterfaceIdentCacheEntry(AVLNode.Data);
|
||||
if (Item^.Node<>nil) and (Item^.Identifier<>nil) then begin
|
||||
if (IdentifierItem=nil)
|
||||
or (CompareIdentifiers(Item^.Identifier,PChar(Pointer(IdentifierItem.Name)))<>0)
|
||||
then begin
|
||||
Changed:=true;
|
||||
break;
|
||||
end;
|
||||
IdentifierItem:=IdentifierItem.NextInUnit;
|
||||
end;
|
||||
AVLNode:=SrcTree.FindSuccessor(AVLNode);
|
||||
end;
|
||||
if IdentifierItem<>nil then
|
||||
Changed:=true; // the old list had more identifiers
|
||||
if Changed then begin
|
||||
// list of identifiers has changed => rebuild
|
||||
CurUnit.ClearIdentifiers;
|
||||
AVLNode:=SrcTree.FindLowest;
|
||||
while AVLNode<>nil do begin
|
||||
Item:=PInterfaceIdentCacheEntry(AVLNode.Data);
|
||||
if (Item^.Node<>nil) and (Item^.Identifier<>nil) then begin
|
||||
IdentifierItem:=TUDIdentifier.Create(Item^.Identifier);
|
||||
CurUnit.AddIdentifier(IdentifierItem);
|
||||
FIdentifiers.Add(IdentifierItem);
|
||||
end;
|
||||
AVLNode:=SrcTree.FindSuccessor(AVLNode);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TUnitDictionary.FindUnitWithFilename(const aFilename: string
|
||||
): TUDUnit;
|
||||
var
|
||||
AVLNode: TAVLTreeNode;
|
||||
begin
|
||||
AVLNode:=FUnitsByFilename.FindKey(Pointer(aFilename),@CompareFileNameWithIDFileItem);
|
||||
if AVLNode<>nil then
|
||||
Result:=TUDUnit(AVLNode.Data)
|
||||
else
|
||||
Result:=nil;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user