|
@@ -147,15 +147,15 @@ type
|
|
|
end;
|
|
|
|
|
|
TPasAnalyzerOption = (
|
|
|
- paoKeepPublished, // when a class is used, all its published members are used as well
|
|
|
paoOnlyExports // default: use all class members accessible from outside (protected, but not private)
|
|
|
);
|
|
|
TPasAnalyzerOptions = set of TPasAnalyzerOption;
|
|
|
|
|
|
TPAUseMode = (
|
|
|
- paumElement, // mark element
|
|
|
- paumAllPublic, // mark element and descend into children and mark public identifiers
|
|
|
- paumAllExports // do not mark element and descend into children and mark exports
|
|
|
+ paumElement, // Mark element. Do not descend into children.
|
|
|
+ paumAllPublic, // Mark element and descend into children and mark public identifiers
|
|
|
+ paumAllExports, // Do not mark element. Descend into children and mark exports.
|
|
|
+ paumPublished // Mark element and its type and descend into children and mark published identifiers
|
|
|
);
|
|
|
TPAUseModes = set of TPAUseMode;
|
|
|
|
|
@@ -188,6 +188,7 @@ type
|
|
|
function ElementVisited(El: TPasElement; Mode: TPAUseMode): boolean;
|
|
|
procedure UseElement(El: TPasElement; Access: TResolvedRefAccess;
|
|
|
UseFull: boolean); virtual;
|
|
|
+ procedure UsePublished(El: TPasElement); virtual;
|
|
|
procedure UseModule(aModule: TPasModule; Mode: TPAUseMode); virtual;
|
|
|
procedure UseSection(Section: TPasSection; Mode: TPAUseMode); virtual;
|
|
|
procedure UseImplBlock(Block: TPasImplBlock; Mark: boolean); virtual;
|
|
@@ -221,6 +222,7 @@ type
|
|
|
function FindElement(El: TPasElement): TPAElement;
|
|
|
// utility
|
|
|
function IsUsed(El: TPasElement): boolean; // valid after calling Analyze*
|
|
|
+ function IsTypeInfoUsed(El: TPasElement): boolean; // valid after calling Analyze*
|
|
|
function IsModuleInternal(El: TPasElement): boolean;
|
|
|
function IsExport(El: TPasElement): boolean;
|
|
|
function IsIdentifier(El: TPasElement): boolean;
|
|
@@ -615,6 +617,80 @@ begin
|
|
|
RaiseNotSupported(20170307090947,El);
|
|
|
end;
|
|
|
|
|
|
+procedure TPasAnalyzer.UsePublished(El: TPasElement);
|
|
|
+// mark typeinfo, do not
|
|
|
+var
|
|
|
+ C: TClass;
|
|
|
+ Members: TFPList;
|
|
|
+ i: Integer;
|
|
|
+ Member: TPasElement;
|
|
|
+ MemberResolved: TPasResolverResult;
|
|
|
+ Prop: TPasProperty;
|
|
|
+ ProcType: TPasProcedureType;
|
|
|
+begin
|
|
|
+ {$IFDEF VerbosePasAnalyzer}
|
|
|
+ writeln('TPasAnalyzer.UsePublished START ',GetObjName(El));
|
|
|
+ {$ENDIF}
|
|
|
+ if ElementVisited(El,paumPublished) then exit;
|
|
|
+ C:=El.ClassType;
|
|
|
+ if C=TPasUnresolvedSymbolRef then
|
|
|
+ else if (C=TPasVariable) or (C=TPasConst) then
|
|
|
+ UsePublished(TPasVariable(El).VarType)
|
|
|
+ else if C=TPasProperty then
|
|
|
+ begin
|
|
|
+ // published property
|
|
|
+ Prop:=TPasProperty(El);
|
|
|
+ for i:=0 to Prop.Args.Count-1 do
|
|
|
+ UsePublished(TPasArgument(Prop.Args[i]).ArgType);
|
|
|
+ UsePublished(Prop.VarType);
|
|
|
+ // Note: read, write and index don't need extra typeinfo
|
|
|
+
|
|
|
+ // stored and defaultvalue are only used when published -> mark as used
|
|
|
+ UseElement(Prop.StoredAccessor,rraRead,false);
|
|
|
+ UseElement(Prop.DefaultExpr,rraRead,false);
|
|
|
+ end
|
|
|
+ else if (C=TPasAliasType) or (C=TPasTypeAliasType) then
|
|
|
+ UsePublished(TPasAliasType(El).DestType)
|
|
|
+ else if C=TPasSetType then
|
|
|
+ UsePublished(TPasSetType(El).EnumType)
|
|
|
+ else if C=TPasArrayType then
|
|
|
+ begin
|
|
|
+ UsePublished(TPasArrayType(El).ElType);
|
|
|
+ for i:=0 to length(TPasArrayType(El).Ranges)-1 do
|
|
|
+ begin
|
|
|
+ Member:=TPasArrayType(El).Ranges[i];
|
|
|
+ Resolver.ComputeElement(Member,MemberResolved,[rcConstant]);
|
|
|
+ UsePublished(MemberResolved.TypeEl);
|
|
|
+ end;
|
|
|
+ end
|
|
|
+ else if C=TPasPointerType then
|
|
|
+ UsePublished(TPasPointerType(El).DestType)
|
|
|
+ else if C=TPasClassType then
|
|
|
+ else if C=TPasClassOfType then
|
|
|
+ else if C=TPasRecordType then
|
|
|
+ begin
|
|
|
+ // published record: use all members
|
|
|
+ Members:=TPasRecordType(El).Members;
|
|
|
+ for i:=0 to Members.Count-1 do
|
|
|
+ begin
|
|
|
+ UsePublished(TPasElement(Members[i]));
|
|
|
+ UseElement(Member,rraNone,true);
|
|
|
+ end;
|
|
|
+ end
|
|
|
+ else if C.InheritsFrom(TPasProcedure) then
|
|
|
+ UsePublished(TPasProcedure(El).ProcType)
|
|
|
+ else if C.InheritsFrom(TPasProcedureType) then
|
|
|
+ begin
|
|
|
+ ProcType:=TPasProcedureType(El);
|
|
|
+ for i:=0 to ProcType.Args.Count-1 do
|
|
|
+ UsePublished(TPasArgument(ProcType.Args[i]).ArgType);
|
|
|
+ if El is TPasFunctionType then
|
|
|
+ UsePublished(TPasFunctionType(El).ResultEl.ResultType);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ RaiseNotSupported(20170414153904,El);
|
|
|
+end;
|
|
|
+
|
|
|
procedure TPasAnalyzer.UseModule(aModule: TPasModule; Mode: TPAUseMode);
|
|
|
|
|
|
procedure UseInitFinal(aSection: TPasImplBlock);
|
|
@@ -1158,7 +1234,7 @@ procedure TPasAnalyzer.UseClassType(El: TPasClassType; Mode: TPAUseMode);
|
|
|
var
|
|
|
i: Integer;
|
|
|
Member: TPasElement;
|
|
|
- UsePublished, FirstTime: Boolean;
|
|
|
+ AllPublished, FirstTime: Boolean;
|
|
|
ProcScope: TPasProcedureScope;
|
|
|
ClassScope: TPasClassScope;
|
|
|
Ref: TResolvedReference;
|
|
@@ -1178,6 +1254,8 @@ begin
|
|
|
end;
|
|
|
paumElement:
|
|
|
if not MarkElementAsUsed(El) then exit;
|
|
|
+ else
|
|
|
+ RaiseInconsistency(20170414152143,IntToStr(ord(Mode)));
|
|
|
end;
|
|
|
{$IFDEF VerbosePasAnalyzer}
|
|
|
writeln('TPasAnalyzer.UseClassType ',GetElModName(El),' ',Mode,' First=',FirstTime);
|
|
@@ -1199,7 +1277,7 @@ begin
|
|
|
UseType(TPasType(El.Interfaces[i]),paumElement);
|
|
|
end;
|
|
|
// members
|
|
|
- UsePublished:=(Mode<>paumAllExports) and (paoKeepPublished in Options);
|
|
|
+ AllPublished:=(Mode<>paumAllExports);
|
|
|
for i:=0 to El.Members.Count-1 do
|
|
|
begin
|
|
|
Member:=TPasElement(El.Members[i]);
|
|
@@ -1209,10 +1287,11 @@ begin
|
|
|
if ProcScope.OverriddenProc<>nil then
|
|
|
AddOverride(ProcScope.OverriddenProc,Member);
|
|
|
end;
|
|
|
- if UsePublished and (Member.Visibility=visPublished) then
|
|
|
+ if AllPublished and (Member.Visibility=visPublished) then
|
|
|
begin
|
|
|
// include published
|
|
|
if not FirstTime then continue;
|
|
|
+ UsePublished(Member);
|
|
|
end
|
|
|
else if Mode=paumElement then
|
|
|
continue
|
|
@@ -1763,6 +1842,11 @@ begin
|
|
|
Result:=FindElement(El)<>nil;
|
|
|
end;
|
|
|
|
|
|
+function TPasAnalyzer.IsTypeInfoUsed(El: TPasElement): boolean;
|
|
|
+begin
|
|
|
+ Result:=FChecked[paumPublished].Find(El)<>nil;
|
|
|
+end;
|
|
|
+
|
|
|
function TPasAnalyzer.IsModuleInternal(El: TPasElement): boolean;
|
|
|
begin
|
|
|
if El=nil then
|
|
@@ -1772,7 +1856,7 @@ begin
|
|
|
if IsExport(El) then exit(false);
|
|
|
case El.Visibility of
|
|
|
visPrivate,visStrictPrivate: exit(true);
|
|
|
- visPublished: if paoKeepPublished in Options then exit(false);
|
|
|
+ visPublished: exit(false);
|
|
|
end;
|
|
|
Result:=IsModuleInternal(El.Parent);
|
|
|
end;
|