mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-15 03:39:30 +02:00
fcl-passrc: adapt pasuseanalyzer for pas2js
git-svn-id: trunk@40013 -
This commit is contained in:
parent
9bd931e931
commit
ce4ccfc0aa
@ -135,6 +135,10 @@ type
|
||||
FParent: TPasElement;
|
||||
FHints : TPasMemberHints;
|
||||
FHintMessage : String;
|
||||
{$ifdef pas2js}
|
||||
FPasElementId: NativeInt;
|
||||
class var FLastPasElementId: NativeInt;
|
||||
{$endif}
|
||||
{$ifdef EnablePasTreeGlobalRefCount}
|
||||
class var FGlobalRefCount: int64;
|
||||
{$endif}
|
||||
@ -175,9 +179,12 @@ type
|
||||
property RefCount: LongWord read FRefCount;
|
||||
property Name: string read FName write FName;
|
||||
property Parent: TPasElement read FParent Write SetParent;
|
||||
Property Hints : TPasMemberHints Read FHints Write FHints;
|
||||
Property HintMessage : String Read FHintMessage Write FHintMessage;
|
||||
Property DocComment : String Read FDocComment Write FDocComment;
|
||||
property Hints : TPasMemberHints Read FHints Write FHints;
|
||||
property HintMessage : String Read FHintMessage Write FHintMessage;
|
||||
property DocComment : String Read FDocComment Write FDocComment;
|
||||
{$ifdef pas2js}
|
||||
property PasElementId: NativeInt read FPasElementId; // global unique id
|
||||
{$endif}
|
||||
{$ifdef EnablePasTreeGlobalRefCount}
|
||||
class property GlobalRefCount: int64 read FGlobalRefCount write FGlobalRefCount;
|
||||
{$endif}
|
||||
@ -2308,6 +2315,10 @@ begin
|
||||
inherited Create;
|
||||
FName := AName;
|
||||
FParent := AParent;
|
||||
{$ifdef pas2js}
|
||||
inc(FLastPasElementId);
|
||||
FPasElementId:=FLastPasElementId;
|
||||
{$endif}
|
||||
{$ifdef EnablePasTreeGlobalRefCount}
|
||||
Inc(FGlobalRefCount);
|
||||
{$endif}
|
||||
|
@ -39,12 +39,23 @@ Working:
|
||||
}
|
||||
unit PasUseAnalyzer;
|
||||
|
||||
{$mode objfpc}{$H+}{$inline on}
|
||||
{$mode objfpc}{$H+}
|
||||
{$inline on}
|
||||
|
||||
{$ifdef fpc}
|
||||
{$define UsePChar}
|
||||
{$define HasInt64}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Types, AVL_Tree,
|
||||
{$ifdef pas2js}
|
||||
js,
|
||||
{$else}
|
||||
AVL_Tree,
|
||||
{$endif}
|
||||
Classes, SysUtils, Types,
|
||||
PasTree, PScanner, PasResolveEval, PasResolver;
|
||||
|
||||
const
|
||||
@ -88,7 +99,7 @@ type
|
||||
private
|
||||
FRefCount: integer;
|
||||
public
|
||||
Id: int64;
|
||||
Id: TMaxPrecInt;
|
||||
MsgType: TMessageType;
|
||||
MsgNumber: integer;
|
||||
MsgText: string;
|
||||
@ -148,6 +159,43 @@ type
|
||||
property Overrides[Index: integer]: TPasElement read GetOverrides; default;
|
||||
end;
|
||||
|
||||
{$ifdef pas2js}
|
||||
TPASItemToNameProc = function(Item: Pointer): String;
|
||||
{$endif}
|
||||
|
||||
{ TPasAnalyzerKeySet - set of items, each item has a key, no duplicate keys }
|
||||
|
||||
TPasAnalyzerKeySet = class
|
||||
private
|
||||
{$ifdef pas2js}
|
||||
FItems: TJSObject;
|
||||
FCount: integer;
|
||||
FItemToName: TPASItemToNameProc;
|
||||
FKeyToName: TPASItemToNameProc;
|
||||
{$else}
|
||||
FTree: TAVLTree; // tree of pointers, sorted for keys given by OnItemToKey, no duplicate keys
|
||||
FCompareKeyWithData: TListSortCompare;
|
||||
{$endif}
|
||||
public
|
||||
{$ifdef pas2js}
|
||||
constructor Create(const OnItemToName, OnKeyToName: TPASItemToNameProc); reintroduce;
|
||||
{$else}
|
||||
constructor Create(const OnCompareMethod: TListSortCompare;
|
||||
const OnCompareKeyWithData: TListSortCompare);
|
||||
{$endif}
|
||||
destructor Destroy; override;
|
||||
procedure Clear;
|
||||
procedure FreeItems;
|
||||
procedure Add(Item: Pointer; CheckDuplicates: boolean = true);
|
||||
procedure Remove(Item: Pointer);
|
||||
function ContainsItem(Item: Pointer): boolean;
|
||||
function ContainsKey(Key: Pointer): boolean;
|
||||
function FindItem(Item: Pointer): Pointer;
|
||||
function FindKey(Key: Pointer): Pointer;
|
||||
function Count: integer;
|
||||
function GetList: TFPList; // list of items
|
||||
end;
|
||||
|
||||
TPasAnalyzerOption = (
|
||||
paoOnlyExports, // default: use all class members accessible from outside (protected, but not private)
|
||||
paoImplReferences // collect references of top lvl proc implementations, initializationa dn finalization sections
|
||||
@ -175,29 +223,26 @@ type
|
||||
|
||||
TPasAnalyzer = class
|
||||
private
|
||||
FChecked: array[TPAUseMode] of TAVLTree; // tree of TElement
|
||||
FChecked: array[TPAUseMode] of TPasAnalyzerKeySet; // tree of TElement
|
||||
FOnMessage: TPAMessageEvent;
|
||||
FOptions: TPasAnalyzerOptions;
|
||||
FOverrideLists: TAVLTree; // tree of TPAOverrideList sorted for Element
|
||||
FOverrideLists: TPasAnalyzerKeySet; // tree of TPAOverrideList sorted for Element
|
||||
FResolver: TPasResolver;
|
||||
FScopeModule: TPasModule;
|
||||
FUsedElements: TAVLTree; // tree of TPAElement sorted for Element
|
||||
FUsedElements: TPasAnalyzerKeySet; // tree of TPAElement sorted for Element
|
||||
procedure UseElType(El: TPasElement; aType: TPasType; Mode: TPAUseMode); inline;
|
||||
function AddOverride(OverriddenEl, OverrideEl: TPasElement): boolean;
|
||||
function FindOverrideNode(El: TPasElement): TAVLTreeNode;
|
||||
function FindOverrideList(El: TPasElement): TPAOverrideList;
|
||||
procedure SetOptions(AValue: TPasAnalyzerOptions);
|
||||
procedure UpdateAccess(IsWrite: Boolean; IsRead: Boolean; Usage: TPAElement);
|
||||
procedure OnUseScopeRef(Data, DeclScope: pointer);
|
||||
protected
|
||||
procedure RaiseInconsistency(const Id: int64; Msg: string);
|
||||
procedure RaiseNotSupported(const Id: int64; El: TPasElement; const Msg: string = '');
|
||||
procedure RaiseInconsistency(const Id: TMaxPrecInt; Msg: string);
|
||||
procedure RaiseNotSupported(const Id: TMaxPrecInt; El: TPasElement; const Msg: string = '');
|
||||
function FindTopImplScope(El: TPasElement): TPasScope;
|
||||
// mark used elements
|
||||
function Add(El: TPasElement; CheckDuplicate: boolean = true;
|
||||
aClass: TPAElementClass = nil): TPAElement;
|
||||
function FindNode(El: TPasElement): TAVLTreeNode; inline;
|
||||
function FindPAElement(El: TPasElement): TPAElement; inline;
|
||||
function PAElementExists(El: TPasElement): boolean; inline;
|
||||
procedure CreateTree; virtual;
|
||||
function MarkElementAsUsed(El: TPasElement; aClass: TPAElementClass = nil): boolean; // true if new
|
||||
function ElementVisited(El: TPasElement; Mode: TPAUseMode): boolean;
|
||||
@ -238,7 +283,7 @@ type
|
||||
procedure AnalyzeModule(aModule: TPasModule);
|
||||
procedure AnalyzeWholeProgram(aStartModule: TPasProgram);
|
||||
procedure EmitModuleHints(aModule: TPasModule); virtual;
|
||||
function FindElement(El: TPasElement): TPAElement;
|
||||
function FindElement(El: TPasElement): TPAElement; inline;
|
||||
function FindUsedElement(El: TPasElement): TPAElement;
|
||||
// utility
|
||||
function IsUsed(El: TPasElement): boolean; // valid after calling Analyze*
|
||||
@ -247,8 +292,10 @@ type
|
||||
function IsExport(El: TPasElement): boolean;
|
||||
function IsIdentifier(El: TPasElement): boolean;
|
||||
function IsImplBlockEmpty(El: TPasImplBlock): boolean;
|
||||
procedure EmitMessage(Id: int64; MsgType: TMessageType;
|
||||
MsgNumber: integer; Fmt: String; const Args: array of const; PosEl: TPasElement);
|
||||
procedure EmitMessage(Id: TMaxPrecInt; MsgType: TMessageType;
|
||||
MsgNumber: integer; Fmt: String;
|
||||
const Args: array of {$ifdef pas2js}jsvalue{$else}const{$endif};
|
||||
PosEl: TPasElement);
|
||||
procedure EmitMessage(Msg: TPAMessage);
|
||||
class function GetWarnIdentifierNumbers(Identifier: string;
|
||||
out MsgNumbers: TIntegerDynArray): boolean; virtual;
|
||||
@ -259,15 +306,43 @@ type
|
||||
property ScopeModule: TPasModule read FScopeModule write FScopeModule;
|
||||
end;
|
||||
|
||||
{$ifdef pas2js}
|
||||
function PasElementToHashName(Item: Pointer): String;
|
||||
function PAElement_ElToHashName(Item: Pointer): String;
|
||||
function PAOverrideList_ElToHashName(Item: Pointer): String;
|
||||
{$else}
|
||||
function ComparePAElements(Identifier1, Identifier2: Pointer): integer;
|
||||
function CompareElementWithPAElement(El, Id: Pointer): integer;
|
||||
function ComparePAOverrideLists(List1, List2: Pointer): integer;
|
||||
function CompareElementWithPAOverrideList(El, List: Pointer): integer;
|
||||
{$endif}
|
||||
function GetElModName(El: TPasElement): string;
|
||||
function dbgs(a: TPAIdentifierAccess): string; overload;
|
||||
|
||||
implementation
|
||||
|
||||
{$ifdef pas2js}
|
||||
function PasElementToHashName(Item: Pointer): String;
|
||||
var
|
||||
El: TPasElement absolute Item;
|
||||
begin
|
||||
Result:=string(jsvalue(El.PasElementId));
|
||||
end;
|
||||
|
||||
function PAElement_ElToHashName(Item: Pointer): String;
|
||||
var
|
||||
El: TPAElement absolute Item;
|
||||
begin
|
||||
Result:=string(jsvalue(El.Element.PasElementId));
|
||||
end;
|
||||
|
||||
function PAOverrideList_ElToHashName(Item: Pointer): String;
|
||||
var
|
||||
List: TPAOverrideList absolute Item;
|
||||
begin
|
||||
Result:=string(jsvalue(List.Element.PasElementId));
|
||||
end;
|
||||
{$else}
|
||||
function ComparePointer(Data1, Data2: Pointer): integer;
|
||||
begin
|
||||
if Data1>Data2 then Result:=-1
|
||||
@ -304,6 +379,7 @@ var
|
||||
begin
|
||||
Result:=ComparePointer(El,OvList.Element);
|
||||
end;
|
||||
{$endif}
|
||||
|
||||
function GetElModName(El: TPasElement): string;
|
||||
var
|
||||
@ -324,6 +400,190 @@ begin
|
||||
str(a,Result);
|
||||
end;
|
||||
|
||||
{ TPasAnalyzerKeySet }
|
||||
|
||||
{$ifdef pas2js}
|
||||
constructor TPasAnalyzerKeySet.Create(const OnItemToName,
|
||||
OnKeyToName: TPASItemToNameProc);
|
||||
begin
|
||||
FItemToName:=OnItemToName;
|
||||
FKeyToName:=OnKeyToName;
|
||||
FItems:=TJSObject.new;
|
||||
end;
|
||||
{$else}
|
||||
constructor TPasAnalyzerKeySet.Create(const OnCompareMethod: TListSortCompare;
|
||||
const OnCompareKeyWithData: TListSortCompare);
|
||||
begin
|
||||
FTree:=TAVLTree.Create(OnCompareMethod);
|
||||
FCompareKeyWithData:=OnCompareKeyWithData;
|
||||
end;
|
||||
{$endif}
|
||||
|
||||
destructor TPasAnalyzerKeySet.Destroy;
|
||||
begin
|
||||
{$ifdef pas2js}
|
||||
FItems:=nil;
|
||||
{$else}
|
||||
FreeAndNil(FTree);
|
||||
{$endif}
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TPasAnalyzerKeySet.Clear;
|
||||
begin
|
||||
{$ifdef pas2js}
|
||||
FItems:=TJSObject.new;
|
||||
FCount:=0;
|
||||
{$else}
|
||||
FTree.Clear;
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
procedure TPasAnalyzerKeySet.FreeItems;
|
||||
{$ifdef pas2js}
|
||||
var
|
||||
List: TStringDynArray;
|
||||
i: Integer;
|
||||
begin
|
||||
List:=TJSObject.getOwnPropertyNames(FItems);
|
||||
for i:=0 to length(List)-1 do
|
||||
TObject(FItems[List[i]]).Destroy;
|
||||
FItems:=TJSObject.new;
|
||||
FCount:=0;
|
||||
end;
|
||||
{$else}
|
||||
begin
|
||||
FTree.FreeAndClear;
|
||||
end;
|
||||
{$endif}
|
||||
|
||||
procedure TPasAnalyzerKeySet.Add(Item: Pointer; CheckDuplicates: boolean);
|
||||
begin
|
||||
if CheckDuplicates then
|
||||
if ContainsItem(Item) then
|
||||
raise Exception.Create('TPasAnalyzerSet.Add duplicate');
|
||||
{$ifdef pas2js}
|
||||
FItems[FItemToName(Item)]:=Item;
|
||||
inc(FCount);
|
||||
{$else}
|
||||
FTree.Add(Item);
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
procedure TPasAnalyzerKeySet.Remove(Item: Pointer);
|
||||
{$ifdef pas2js}
|
||||
var
|
||||
aName: string;
|
||||
begin
|
||||
aName:=FItemToName(Item);
|
||||
if not FItems.hasOwnProperty(aName) then exit;
|
||||
JSDelete(FItems,aName);
|
||||
dec(FCount);
|
||||
end;
|
||||
{$else}
|
||||
begin
|
||||
FTree.Remove(Item);
|
||||
end;
|
||||
{$endif}
|
||||
|
||||
function TPasAnalyzerKeySet.ContainsItem(Item: Pointer): boolean;
|
||||
begin
|
||||
{$ifdef pas2js}
|
||||
Result:=FItems.hasOwnProperty(FItemToName(Item));
|
||||
{$else}
|
||||
Result:=FTree.Find(Item)<>nil;
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
function TPasAnalyzerKeySet.ContainsKey(Key: Pointer): boolean;
|
||||
begin
|
||||
{$ifdef pas2js}
|
||||
Result:=FItems.hasOwnProperty(FKeyToName(Key));
|
||||
{$else}
|
||||
Result:=FTree.FindKey(Key,FCompareKeyWithData)<>nil;
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
function TPasAnalyzerKeySet.FindItem(Item: Pointer): Pointer;
|
||||
{$ifdef pas2js}
|
||||
var
|
||||
aName: string;
|
||||
begin
|
||||
aName:=FItemToName(Item);
|
||||
if not FItems.hasOwnProperty(aName) then
|
||||
exit(nil)
|
||||
else
|
||||
Result:=Pointer(FItems[aName]);
|
||||
end;
|
||||
{$else}
|
||||
var
|
||||
Node: TAVLTreeNode;
|
||||
begin
|
||||
Node:=FTree.Find(Item);
|
||||
if Node<>nil then
|
||||
Result:=Node.Data
|
||||
else
|
||||
Result:=nil;
|
||||
end;
|
||||
{$endif}
|
||||
|
||||
function TPasAnalyzerKeySet.FindKey(Key: Pointer): Pointer;
|
||||
{$ifdef pas2js}
|
||||
var
|
||||
aName: string;
|
||||
begin
|
||||
aName:=FKeyToName(Key);
|
||||
if not FItems.hasOwnProperty(aName) then
|
||||
exit(nil)
|
||||
else
|
||||
Result:=Pointer(FItems[aName]);
|
||||
end;
|
||||
{$else}
|
||||
var
|
||||
Node: TAVLTreeNode;
|
||||
begin
|
||||
Node:=FTree.FindKey(Key,FCompareKeyWithData);
|
||||
if Node<>nil then
|
||||
Result:=Node.Data
|
||||
else
|
||||
Result:=nil;
|
||||
end;
|
||||
{$endif}
|
||||
|
||||
function TPasAnalyzerKeySet.Count: integer;
|
||||
begin
|
||||
{$ifdef pas2js}
|
||||
Result:=FCount;
|
||||
{$else}
|
||||
Result:=FTree.Count;
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
function TPasAnalyzerKeySet.GetList: TFPList;
|
||||
{$ifdef pas2js}
|
||||
var
|
||||
List: TStringDynArray;
|
||||
i: Integer;
|
||||
begin
|
||||
List:=TJSObject.getOwnPropertyNames(FItems);
|
||||
Result:=TFPList.Create;
|
||||
for i:=0 to length(List)-1 do
|
||||
Result.Add(FItems[List[i]]);
|
||||
end;
|
||||
{$else}
|
||||
var
|
||||
Node: TAVLTreeNode;
|
||||
begin
|
||||
Result:=TFPList.Create;
|
||||
Node:=FTree.FindLowest;
|
||||
while Node<>nil do
|
||||
begin
|
||||
Result.Add(Node.Data);
|
||||
Node:=FTree.FindSuccessor(Node);
|
||||
end;
|
||||
end;
|
||||
{$endif}
|
||||
|
||||
{ TPAMessage }
|
||||
|
||||
constructor TPAMessage.Create;
|
||||
@ -342,7 +602,11 @@ begin
|
||||
raise Exception.Create('');
|
||||
dec(FRefCount);
|
||||
if FRefCount=0 then
|
||||
{$ifdef pas2js}
|
||||
Destroy;
|
||||
{$else}
|
||||
Free;
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
{ TPAOverrideList }
|
||||
@ -417,21 +681,9 @@ end;
|
||||
{ TPasAnalyzer }
|
||||
|
||||
// inline
|
||||
function TPasAnalyzer.FindNode(El: TPasElement): TAVLTreeNode;
|
||||
function TPasAnalyzer.PAElementExists(El: TPasElement): boolean;
|
||||
begin
|
||||
Result:=FUsedElements.FindKey(El,@CompareElementWithPAElement);
|
||||
end;
|
||||
|
||||
// inline
|
||||
function TPasAnalyzer.FindPAElement(El: TPasElement): TPAElement;
|
||||
var
|
||||
Node: TAVLTreeNode;
|
||||
begin
|
||||
Node:=FindNode(El);
|
||||
if Node=nil then
|
||||
Result:=nil
|
||||
else
|
||||
Result:=TPAElement(Node.Data);
|
||||
Result:=FUsedElements.ContainsKey(El);
|
||||
end;
|
||||
|
||||
// inline
|
||||
@ -443,33 +695,22 @@ begin
|
||||
UseType(aType,Mode);
|
||||
end;
|
||||
|
||||
// inline
|
||||
function TPasAnalyzer.FindElement(El: TPasElement): TPAElement;
|
||||
begin
|
||||
Result:=TPAElement(FUsedElements.FindKey(El));
|
||||
end;
|
||||
|
||||
procedure TPasAnalyzer.SetOptions(AValue: TPasAnalyzerOptions);
|
||||
begin
|
||||
if FOptions=AValue then Exit;
|
||||
FOptions:=AValue;
|
||||
end;
|
||||
|
||||
function TPasAnalyzer.FindOverrideNode(El: TPasElement): TAVLTreeNode;
|
||||
begin
|
||||
Result:=FOverrideLists.FindKey(El,@CompareElementWithPAOverrideList);
|
||||
end;
|
||||
|
||||
function TPasAnalyzer.FindOverrideList(El: TPasElement): TPAOverrideList;
|
||||
var
|
||||
Node: TAVLTreeNode;
|
||||
begin
|
||||
Node:=FindOverrideNode(El);
|
||||
if Node=nil then
|
||||
Result:=nil
|
||||
else
|
||||
Result:=TPAOverrideList(Node.Data);
|
||||
end;
|
||||
|
||||
function TPasAnalyzer.AddOverride(OverriddenEl, OverrideEl: TPasElement): boolean;
|
||||
// OverrideEl overrides OverriddenEl
|
||||
// returns true if new override
|
||||
var
|
||||
Node: TAVLTreeNode;
|
||||
Item: TPAOverrideList;
|
||||
OverriddenPAEl: TPAElement;
|
||||
TypeEl: TPasType;
|
||||
@ -477,16 +718,15 @@ begin
|
||||
{$IFDEF VerbosePasAnalyzer}
|
||||
writeln('TPasAnalyzer.AddOverride OverriddenEl=',GetElModName(OverriddenEl),' OverrideEl=',GetElModName(OverrideEl));
|
||||
{$ENDIF}
|
||||
Node:=FindOverrideNode(OverriddenEl);
|
||||
if Node=nil then
|
||||
Item:=TPAOverrideList(FOverrideLists.FindKey(OverriddenEl));
|
||||
if Item=nil then
|
||||
begin
|
||||
Item:=TPAOverrideList.Create;
|
||||
Item.Element:=OverriddenEl;
|
||||
FOverrideLists.Add(Item);
|
||||
FOverrideLists.Add(Item,false);
|
||||
end
|
||||
else
|
||||
begin
|
||||
Item:=TPAOverrideList(Node.Data);
|
||||
if Item.IndexOf(OverrideEl)>=0 then
|
||||
exit(false);
|
||||
end;
|
||||
@ -494,7 +734,7 @@ begin
|
||||
Item.Add(OverrideEl);
|
||||
Result:=true;
|
||||
|
||||
OverriddenPAEl:=FindPAElement(OverriddenEl);
|
||||
OverriddenPAEl:=FindElement(OverriddenEl);
|
||||
if OverriddenPAEl<>nil then
|
||||
begin
|
||||
// OverriddenEl was already used -> use OverrideEl
|
||||
@ -567,7 +807,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TPasAnalyzer.RaiseInconsistency(const Id: int64; Msg: string);
|
||||
procedure TPasAnalyzer.RaiseInconsistency(const Id: TMaxPrecInt; Msg: string);
|
||||
begin
|
||||
{$IFDEF VerbosePasAnalyzer}
|
||||
writeln('TPasAnalyzer.RaiseInconsistency ['+IntToStr(Id)+']: '+Msg);
|
||||
@ -575,7 +815,7 @@ begin
|
||||
raise EPasAnalyzer.Create('['+IntToStr(Id)+']: '+Msg);
|
||||
end;
|
||||
|
||||
procedure TPasAnalyzer.RaiseNotSupported(const Id: int64; El: TPasElement;
|
||||
procedure TPasAnalyzer.RaiseNotSupported(const Id: TMaxPrecInt; El: TPasElement;
|
||||
const Msg: string);
|
||||
var
|
||||
s: String;
|
||||
@ -626,9 +866,9 @@ begin
|
||||
if El=nil then
|
||||
RaiseInconsistency(20170308093407,'');
|
||||
{$IFDEF VerbosePasAnalyzer}
|
||||
writeln('TPasAnalyzer.Add ',GetElModName(El),' New=',FindNode(El)=nil);
|
||||
writeln('TPasAnalyzer.Add ',GetElModName(El),' New=',not PAElementExists(El));
|
||||
{$ENDIF}
|
||||
if CheckDuplicate and (FindNode(El)<>nil) then
|
||||
if CheckDuplicate and PAElementExists(El) then
|
||||
RaiseInconsistency(20170304201318,'');
|
||||
if aClass=nil then
|
||||
aClass:=TPAElement;
|
||||
@ -636,13 +876,18 @@ begin
|
||||
Result.Element:=El;
|
||||
FUsedElements.Add(Result);
|
||||
{$IFDEF VerbosePasAnalyzer}
|
||||
//writeln('TPasAnalyzer.Add END ',GetElModName(El),' Success=',FindNode(El)<>nil,' ',ptruint(pointer(El)));
|
||||
//writeln('TPasAnalyzer.Add END ',GetElModName(El),' Success=',PAElementExists(El),' ',ptruint(pointer(El)));
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure TPasAnalyzer.CreateTree;
|
||||
begin
|
||||
FUsedElements:=TAVLTree.Create(@ComparePAElements);
|
||||
FUsedElements:=TPasAnalyzerKeySet.Create(
|
||||
{$ifdef pas2js}
|
||||
@PAElement_ElToHashName,@PasElementToHashName
|
||||
{$else}
|
||||
@ComparePAElements,@CompareElementWithPAElement
|
||||
{$endif});
|
||||
end;
|
||||
|
||||
function TPasAnalyzer.MarkElementAsUsed(El: TPasElement; aClass: TPAElementClass
|
||||
@ -650,7 +895,7 @@ function TPasAnalyzer.MarkElementAsUsed(El: TPasElement; aClass: TPAElementClass
|
||||
|
||||
function MarkModule(CurModule: TPasModule): boolean;
|
||||
begin
|
||||
if FindNode(CurModule)<>nil then
|
||||
if PAElementExists(CurModule) then
|
||||
exit(false);
|
||||
{$IFDEF VerbosePasAnalyzer}
|
||||
writeln('TPasAnalyzer.MarkElement.MarkModule mark "',GetElModName(CurModule),'"');
|
||||
@ -686,7 +931,7 @@ begin
|
||||
end;
|
||||
|
||||
// mark element
|
||||
if FindNode(El)<>nil then exit(false);
|
||||
if PAElementExists(El) then exit(false);
|
||||
Add(El,false,aClass);
|
||||
Result:=true;
|
||||
|
||||
@ -705,9 +950,9 @@ function TPasAnalyzer.ElementVisited(El: TPasElement; Mode: TPAUseMode
|
||||
begin
|
||||
if El=nil then
|
||||
exit(true);
|
||||
if FChecked[Mode].Find(El)<>nil then exit(true);
|
||||
if FChecked[Mode].ContainsItem(El) then exit(true);
|
||||
Result:=false;
|
||||
FChecked[Mode].Add(El);
|
||||
FChecked[Mode].Add(El,false);
|
||||
end;
|
||||
|
||||
procedure TPasAnalyzer.MarkImplScopeRef(El, RefEl: TPasElement;
|
||||
@ -900,7 +1145,7 @@ procedure TPasAnalyzer.UseModule(aModule: TPasModule; Mode: TPAUseMode);
|
||||
UseScopeReferences(Scope.References);
|
||||
if (Scope.References=nil) and IsImplBlockEmpty(ImplBlock) then exit;
|
||||
// this module has an initialization section -> mark module
|
||||
if FindNode(aModule)=nil then
|
||||
if not PAElementExists(aModule) then
|
||||
Add(aModule);
|
||||
UseImplBlock(ImplBlock,true);
|
||||
end;
|
||||
@ -936,7 +1181,7 @@ begin
|
||||
|
||||
if Mode=paumElement then
|
||||
// e.g. a reference: unitname.identifier
|
||||
if FindNode(aModule)=nil then
|
||||
if not PAElementExists(aModule) then
|
||||
Add(aModule);
|
||||
end;
|
||||
|
||||
@ -979,7 +1224,7 @@ begin
|
||||
if IsImplBlockEmpty(UsedModule.InitializationSection)
|
||||
and IsImplBlockEmpty(UsedModule.FinalizationSection) then
|
||||
continue;
|
||||
if FindNode(UsedModule)=nil then
|
||||
if not PAElementExists(UsedModule) then
|
||||
Add(UsedModule);
|
||||
UseImplBlock(UsedModule.InitializationSection,true);
|
||||
UseImplBlock(UsedModule.FinalizationSection,true);
|
||||
@ -1427,7 +1672,7 @@ procedure TPasAnalyzer.UseProcedure(Proc: TPasProcedure);
|
||||
i: Integer;
|
||||
OverrideProc: TPasProcedure;
|
||||
begin
|
||||
OverrideList:=FindOverrideList(CurProc);
|
||||
OverrideList:=TPAOverrideList(FOverrideLists.FindKey(CurProc));
|
||||
if OverrideList=nil then exit;
|
||||
// Note: while traversing the OverrideList it may grow
|
||||
i:=0;
|
||||
@ -1637,7 +1882,7 @@ procedure TPasAnalyzer.UseClassType(El: TPasClassType; Mode: TPAUseMode);
|
||||
i: Integer;
|
||||
Prop: TPasProperty;
|
||||
begin
|
||||
OverrideList:=FindOverrideList(El);
|
||||
OverrideList:=TPAOverrideList(FOverrideLists.FindKey(El));
|
||||
if OverrideList=nil then exit;
|
||||
// Note: while traversing the OverrideList it may grow
|
||||
i:=0;
|
||||
@ -2099,7 +2344,7 @@ begin
|
||||
begin
|
||||
UsedModule:=TPasModule(Use.Module);
|
||||
if CompareText(UsedModule.Name,'system')=0 then continue;
|
||||
if FindNode(UsedModule)=nil then
|
||||
if not PAElementExists(UsedModule) then
|
||||
EmitMessage(20170311191725,mtHint,nPAUnitNotUsed,sPAUnitNotUsed,
|
||||
[UsedModule.Name,aModule.Name],Use.Expr);
|
||||
end;
|
||||
@ -2128,7 +2373,7 @@ begin
|
||||
EmitProcedureHints(TPasProcedure(Decl))
|
||||
else
|
||||
begin
|
||||
Usage:=FindPAElement(Decl);
|
||||
Usage:=FindElement(Decl);
|
||||
if Usage=nil then
|
||||
begin
|
||||
// declaration was never used
|
||||
@ -2149,7 +2394,7 @@ begin
|
||||
{$IFDEF VerbosePasAnalyzer}
|
||||
writeln('TPasAnalyzer.EmitTypeHints ',GetElModName(El));
|
||||
{$ENDIF}
|
||||
Usage:=FindPAElement(El);
|
||||
Usage:=FindElement(El);
|
||||
if Usage=nil then
|
||||
begin
|
||||
// the whole type was never used
|
||||
@ -2191,7 +2436,7 @@ begin
|
||||
{$IFDEF VerbosePasAnalyzer}
|
||||
writeln('TPasAnalyzer.EmitVariableHints ',GetElModName(El));
|
||||
{$ENDIF}
|
||||
Usage:=FindPAElement(El);
|
||||
Usage:=FindElement(El);
|
||||
if Usage=nil then
|
||||
begin
|
||||
// not used
|
||||
@ -2251,7 +2496,7 @@ begin
|
||||
ImplProc:=El
|
||||
else
|
||||
ImplProc:=ProcScope.ImplProc;
|
||||
if FindNode(DeclProc)=nil then
|
||||
if not PAElementExists(DeclProc) then
|
||||
begin
|
||||
// procedure never used
|
||||
if ProcScope.DeclarationProc=nil then
|
||||
@ -2282,7 +2527,7 @@ begin
|
||||
for i:=0 to Args.Count-1 do
|
||||
begin
|
||||
Arg:=TPasArgument(Args[i]);
|
||||
Usage:=FindPAElement(Arg);
|
||||
Usage:=FindElement(Arg);
|
||||
if (Usage=nil) or (Usage.Access=paiaNone) then
|
||||
begin
|
||||
// parameter was never used
|
||||
@ -2308,7 +2553,7 @@ begin
|
||||
PosEl:=TPasFunction(El).FuncType.ResultEl;
|
||||
if (ProcScope.ImplProc<>nil) and (TPasFunction(ProcScope.ImplProc).FuncType.ResultEl<>nil) then
|
||||
PosEl:=TPasFunction(ProcScope.ImplProc).FuncType.ResultEl;
|
||||
Usage:=FindPAElement(TPasFunction(El).FuncType.ResultEl);
|
||||
Usage:=FindElement(TPasFunction(El).FuncType.ResultEl);
|
||||
if (Usage=nil) or (Usage.Access in [paiaNone,paiaRead]) then
|
||||
// result was never used
|
||||
EmitMessage(20170313214038,mtHint,nPAFunctionResultDoesNotSeemToBeSet,
|
||||
@ -2334,8 +2579,20 @@ var
|
||||
begin
|
||||
CreateTree;
|
||||
for m in TPAUseMode do
|
||||
FChecked[m]:=TAVLTree.Create;
|
||||
FOverrideLists:=TAVLTree.Create(@ComparePAOverrideLists);
|
||||
FChecked[m]:=TPasAnalyzerKeySet.Create(
|
||||
{$ifdef pas2js}
|
||||
@PasElementToHashName
|
||||
{$else}
|
||||
@ComparePointer
|
||||
{$endif}
|
||||
,nil
|
||||
);
|
||||
FOverrideLists:=TPasAnalyzerKeySet.Create(
|
||||
{$ifdef pas2js}
|
||||
@PAOverrideList_ElToHashName,@PasElementToHashName
|
||||
{$else}
|
||||
@ComparePAOverrideLists,@CompareElementWithPAOverrideList
|
||||
{$endif});
|
||||
end;
|
||||
|
||||
destructor TPasAnalyzer.Destroy;
|
||||
@ -2354,8 +2611,8 @@ procedure TPasAnalyzer.Clear;
|
||||
var
|
||||
m: TPAUseMode;
|
||||
begin
|
||||
FOverrideLists.FreeAndClear;
|
||||
FUsedElements.FreeAndClear;
|
||||
FOverrideLists.FreeItems;
|
||||
FUsedElements.FreeItems;
|
||||
for m in TPAUseMode do
|
||||
FChecked[m].Clear;
|
||||
end;
|
||||
@ -2418,17 +2675,6 @@ begin
|
||||
//EmitBlockHints(aModule.FinalizationSection);
|
||||
end;
|
||||
|
||||
function TPasAnalyzer.FindElement(El: TPasElement): TPAElement;
|
||||
var
|
||||
Node: TAVLTreeNode;
|
||||
begin
|
||||
Node:=FindNode(El);
|
||||
if Node=nil then
|
||||
Result:=nil
|
||||
else
|
||||
Result:=TPAElement(Node.Data);
|
||||
end;
|
||||
|
||||
function TPasAnalyzer.FindUsedElement(El: TPasElement): TPAElement;
|
||||
var
|
||||
ProcScope: TPasProcedureScope;
|
||||
@ -2450,7 +2696,7 @@ end;
|
||||
|
||||
function TPasAnalyzer.IsTypeInfoUsed(El: TPasElement): boolean;
|
||||
begin
|
||||
Result:=FChecked[paumTypeInfo].Find(El)<>nil;
|
||||
Result:=FChecked[paumTypeInfo].ContainsItem(El);
|
||||
end;
|
||||
|
||||
function TPasAnalyzer.IsModuleInternal(El: TPasElement): boolean;
|
||||
@ -2497,8 +2743,9 @@ begin
|
||||
Result:=false;
|
||||
end;
|
||||
|
||||
procedure TPasAnalyzer.EmitMessage(Id: int64; MsgType: TMessageType;
|
||||
MsgNumber: integer; Fmt: String; const Args: array of const;
|
||||
procedure TPasAnalyzer.EmitMessage(Id: TMaxPrecInt; MsgType: TMessageType;
|
||||
MsgNumber: integer; Fmt: String;
|
||||
const Args: array of {$ifdef pas2js}jsvalue{$else}const{$endif};
|
||||
PosEl: TPasElement);
|
||||
var
|
||||
Msg: TPAMessage;
|
||||
@ -2617,16 +2864,8 @@ begin
|
||||
end;
|
||||
|
||||
function TPasAnalyzer.GetUsedElements: TFPList;
|
||||
var
|
||||
Node: TAVLTreeNode;
|
||||
begin
|
||||
Result:=TFPList.Create;
|
||||
Node:=FUsedElements.FindLowest;
|
||||
while Node<>nil do
|
||||
begin
|
||||
Result.Add(Node.Data);
|
||||
Node:=FUsedElements.FindSuccessor(Node);
|
||||
end;
|
||||
Result:=FUsedElements.GetList;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user