mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-08 10:59:10 +02:00
fcl-passrc: parser: create usesclause
git-svn-id: trunk@36006 -
This commit is contained in:
parent
d5d53e7017
commit
d7163d3854
@ -1137,7 +1137,7 @@ type
|
||||
Access: TResolvedRefAccess); virtual;
|
||||
procedure AccessExpr(Expr: TPasExpr; Access: TResolvedRefAccess);
|
||||
procedure FinishModule(CurModule: TPasModule); virtual;
|
||||
procedure FinishUsesList; virtual;
|
||||
procedure FinishUsesClause; virtual;
|
||||
procedure FinishTypeSection(El: TPasDeclarations); virtual;
|
||||
procedure FinishTypeDef(El: TPasType); virtual;
|
||||
procedure FinishEnumType(El: TPasEnumType); virtual;
|
||||
@ -3025,54 +3025,56 @@ begin
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure TPasResolver.FinishUsesList;
|
||||
procedure TPasResolver.FinishUsesClause;
|
||||
var
|
||||
Section: TPasSection;
|
||||
i: Integer;
|
||||
El, PublicEl: TPasElement;
|
||||
PublicEl, UseModule: TPasElement;
|
||||
Scope: TPasSectionScope;
|
||||
UsesScope: TPasIdentifierScope;
|
||||
UseUnit: TPasUsesUnit;
|
||||
begin
|
||||
CheckTopScope(TPasSectionScope);
|
||||
Scope:=TPasSectionScope(TopScope);
|
||||
Section:=TPasSection(Scope.Element);
|
||||
{$IFDEF VerbosePasResolver}
|
||||
writeln('TPasResolver.FinishUsesList Section=',Section.ClassName,' Section.UsesList.Count=',Section.UsesList.Count);
|
||||
writeln('TPasResolver.FinishUsesClause Section=',Section.ClassName,' Section.UsesList.Count=',Section.UsesList.Count);
|
||||
{$ENDIF}
|
||||
for i:=0 to Section.UsesList.Count-1 do
|
||||
begin
|
||||
El:=TPasElement(Section.UsesList[i]);
|
||||
UseUnit:=Section.UsesClause[i];
|
||||
{$IFDEF VerbosePasResolver}
|
||||
writeln('TPasResolver.FinishUsesList ',GetObjName(El));
|
||||
writeln('TPasResolver.FinishUsesClause ',GetObjName(UseUnit));
|
||||
{$ENDIF}
|
||||
if (El.ClassType=TProgramSection) then
|
||||
RaiseInternalError(20160922163346,'used unit is a program: '+GetObjName(El));
|
||||
UseModule:=UseUnit.Module;
|
||||
if (UseModule.ClassType=TProgramSection) then
|
||||
RaiseInternalError(20160922163346,'used unit is a program: '+GetObjName(UseModule));
|
||||
|
||||
// add unitname as identifier
|
||||
AddIdentifier(Scope,El.Name,El,pikSimple);
|
||||
AddIdentifier(Scope,UseUnit.Name,UseModule,pikSimple);
|
||||
|
||||
// check used unit
|
||||
PublicEl:=nil;
|
||||
if (El.ClassType=TLibrarySection) then
|
||||
PublicEl:=El
|
||||
else if (El.ClassType=TPasModule) then
|
||||
PublicEl:=TPasModule(El).InterfaceSection;
|
||||
if (UseModule.ClassType=TLibrarySection) then
|
||||
PublicEl:=UseModule
|
||||
else if (UseModule.ClassType=TPasModule) then
|
||||
PublicEl:=TPasModule(UseModule).InterfaceSection;
|
||||
if PublicEl=nil then
|
||||
RaiseInternalError(20160922163352,'uses element has no interface section: '+GetObjName(El));
|
||||
RaiseInternalError(20160922163352,'uses element has no interface section: '+GetObjName(UseModule));
|
||||
if PublicEl.CustomData=nil then
|
||||
RaiseInternalError(20160922163358,'uses element has no resolver data: '
|
||||
+El.Name+'->'+GetObjName(PublicEl));
|
||||
+UseUnit.Name+'->'+GetObjName(PublicEl));
|
||||
if not (PublicEl.CustomData is TPasIdentifierScope) then
|
||||
RaiseInternalError(20160922163403,'uses element has invalid resolver data: '
|
||||
+El.Name+'->'+GetObjName(PublicEl)+'->'+PublicEl.CustomData.ClassName);
|
||||
+UseUnit.Name+'->'+GetObjName(PublicEl)+'->'+PublicEl.CustomData.ClassName);
|
||||
|
||||
UsesScope:=TPasIdentifierScope(PublicEl.CustomData);
|
||||
{$IFDEF VerbosePasResolver}
|
||||
writeln('TPasResolver.FinishUsesList Add UsesScope=',GetObjName(UsesScope));
|
||||
writeln('TPasResolver.FinishUsesClause Add UsesScope=',GetObjName(UsesScope));
|
||||
{$ENDIF}
|
||||
Scope.UsesList.Add(UsesScope);
|
||||
|
||||
EmitElementHints(Section,El);
|
||||
EmitElementHints(Section,UseUnit);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -8569,7 +8571,7 @@ procedure TPasResolver.FinishScope(ScopeType: TPasScopeType; El: TPasElement);
|
||||
begin
|
||||
case ScopeType of
|
||||
stModule: FinishModule(El as TPasModule);
|
||||
stUsesList: FinishUsesList;
|
||||
stUsesClause: FinishUsesClause;
|
||||
stTypeSection: FinishTypeSection(El as TPasDeclarations);
|
||||
stTypeDef: FinishTypeDef(El as TPasType);
|
||||
stConstDef: FinishConstDef(El as TPasConst);
|
||||
@ -11656,11 +11658,18 @@ begin
|
||||
ResolvedEl.IdentEl:=El;
|
||||
ResolvedEl.Flags:=[rrfReadable,rrfWritable];
|
||||
end
|
||||
else if El is TPasModule then
|
||||
else if ElClass=TPasUsesUnit then
|
||||
begin
|
||||
if TPasUsesUnit(El).Module is TPasModule then
|
||||
SetResolverIdentifier(ResolvedEl,btModule,TPasUsesUnit(El).Module,nil,[])
|
||||
else
|
||||
RaiseNotYetImplemented(20170429112047,TPasUsesUnit(El).Module);
|
||||
end
|
||||
else if El.InheritsFrom(TPasModule) then
|
||||
SetResolverIdentifier(ResolvedEl,btModule,El,nil,[])
|
||||
else if ElClass=TNilExpr then
|
||||
SetResolverValueExpr(ResolvedEl,btNil,FBaseTypes[btNil],TNilExpr(El),[rrfReadable])
|
||||
else if El is TPasProcedure then
|
||||
else if El.InheritsFrom(TPasProcedure) then
|
||||
begin
|
||||
SetResolverIdentifier(ResolvedEl,btProc,El,TPasProcedure(El).ProcType,[rrfCanBeStatement]);
|
||||
if El is TPasFunction then
|
||||
@ -11668,7 +11677,7 @@ begin
|
||||
// Note: the readability of TPasConstructor depends on the context
|
||||
// Note: implicit calls are handled in TPrimitiveExpr
|
||||
end
|
||||
else if El is TPasProcedureType then
|
||||
else if El.InheritsFrom(TPasProcedureType) then
|
||||
begin
|
||||
SetResolverIdentifier(ResolvedEl,btContext,El,TPasProcedureType(El),[rrfCanBeStatement]);
|
||||
// Note: implicit calls are handled in TPrimitiveExpr
|
||||
|
@ -195,7 +195,7 @@ begin
|
||||
If not Assigned(ASection) then exit;
|
||||
if ASection.UsesList.Count=length(ASection.UsesClause) then
|
||||
For I:=0 to length(ASection.UsesClause)-1 do
|
||||
List.Add(ASection.UsesClause[i].Identifier)
|
||||
List.Add(ASection.UsesClause[i].Name)
|
||||
else
|
||||
For I:=0 to ASection.UsesList.Count-1 do
|
||||
List.Add(TPasElement(ASection.UsesList[i]).Name);
|
||||
|
@ -319,10 +319,9 @@ type
|
||||
procedure ForEachCall(const aMethodCall: TOnForEachPasElement;
|
||||
const Arg: Pointer); override;
|
||||
public
|
||||
Expr: TPasExpr;
|
||||
Identifier: string; // e.g. 'name.space.unitname'
|
||||
Expr: TPasExpr; // name expression
|
||||
InFilename: TPrimitiveExpr; // Kind=pekString, can be nil
|
||||
Module: TPasElement; // TPasUnresolvedTypeRef or TPasModule
|
||||
Module: TPasElement; // TPasUnresolvedUnitRef or TPasModule
|
||||
end;
|
||||
TPasUsesClause = array of TPasUsesUnit;
|
||||
|
||||
@ -332,12 +331,13 @@ type
|
||||
public
|
||||
constructor Create(const AName: string; AParent: TPasElement); override;
|
||||
destructor Destroy; override;
|
||||
procedure AddUnitToUsesList(const AUnitName: string);
|
||||
function AddUnitToUsesList(const AUnitName: string; aName: TPasExpr = nil;
|
||||
InFilename: TPrimitiveExpr = nil; aModule: TPasElement = nil): TPasUsesUnit;
|
||||
function ElementTypeName: string; override;
|
||||
procedure ForEachCall(const aMethodCall: TOnForEachPasElement;
|
||||
const Arg: Pointer); override;
|
||||
public
|
||||
UsesList: TFPList; // kept for compatibility, see UsesClause Module
|
||||
UsesList: TFPList; // kept for compatibility, see TPasUsesUnit.Module
|
||||
UsesClause: TPasUsesClause;
|
||||
end;
|
||||
|
||||
@ -4028,14 +4028,26 @@ begin
|
||||
{$IFDEF VerbosePasTreeMem}writeln('TPasSection.Destroy END');{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure TPasSection.AddUnitToUsesList(const AUnitName: string);
|
||||
function TPasSection.AddUnitToUsesList(const AUnitName: string;
|
||||
aName: TPasExpr; InFilename: TPrimitiveExpr; aModule: TPasElement
|
||||
): TPasUsesUnit;
|
||||
var
|
||||
l: Integer;
|
||||
begin
|
||||
UsesList.Add(TPasUnresolvedTypeRef.Create(AUnitName, Self));
|
||||
if (InFilename<>nil) and (InFilename.Kind<>pekString) then
|
||||
raise Exception.Create('');
|
||||
if aModule=nil then
|
||||
aModule:=TPasUnresolvedUnitRef.Create(AUnitName, Self);
|
||||
l:=length(UsesClause);
|
||||
SetLength(UsesClause,l+1);
|
||||
UsesClause[l]:=TPasUsesUnit.Create(AUnitName,Self);
|
||||
Result:=TPasUsesUnit.Create(AUnitName,Self);
|
||||
UsesClause[l]:=Result;
|
||||
Result.Expr:=aName;
|
||||
Result.InFilename:=InFilename;
|
||||
Result.Module:=aModule;
|
||||
|
||||
UsesList.Add(aModule);
|
||||
aModule.AddRef;
|
||||
end;
|
||||
|
||||
function TPasSection.ElementTypeName: string;
|
||||
|
@ -740,11 +740,11 @@ end;
|
||||
procedure TPasAnalyzer.UseSection(Section: TPasSection; Mode: TPAUseMode);
|
||||
// called by UseModule
|
||||
var
|
||||
UsesList: TFPList;
|
||||
i: Integer;
|
||||
UsedModule: TPasModule;
|
||||
Decl: TPasElement;
|
||||
OnlyExports: Boolean;
|
||||
UsesClause: TPasUsesClause;
|
||||
begin
|
||||
// Section is TProgramSection, TLibrarySection, TInterfaceSection, TImplementationSection
|
||||
if Mode=paumElement then
|
||||
@ -760,12 +760,12 @@ begin
|
||||
{$ENDIF}
|
||||
|
||||
// used units
|
||||
UsesList:=Section.UsesList;
|
||||
for i:=0 to UsesList.Count-1 do
|
||||
UsesClause:=Section.UsesClause;
|
||||
for i:=0 to length(UsesClause)-1 do
|
||||
begin
|
||||
if TObject(UsesList[i]) is TPasModule then
|
||||
if UsesClause[i].Module is TPasModule then
|
||||
begin
|
||||
UsedModule:=TPasModule(UsesList[i]);
|
||||
UsedModule:=TPasModule(UsesClause[i].Module);
|
||||
if ScopeModule=nil then
|
||||
// whole program analysis
|
||||
UseModule(UsedModule,paumAllExports)
|
||||
@ -1563,21 +1563,21 @@ end;
|
||||
|
||||
procedure TPasAnalyzer.EmitSectionHints(Section: TPasSection);
|
||||
var
|
||||
UsesList: TFPList;
|
||||
i: Integer;
|
||||
UsedModule, aModule: TPasModule;
|
||||
UsesClause: TPasUsesClause;
|
||||
begin
|
||||
{$IFDEF VerbosePasAnalyzer}
|
||||
writeln('TPasAnalyzer.EmitSectionHints ',GetElModName(Section));
|
||||
{$ENDIF}
|
||||
// initialization, program or library sections
|
||||
aModule:=Section.GetModule;
|
||||
UsesList:=Section.UsesList;
|
||||
for i:=0 to UsesList.Count-1 do
|
||||
UsesClause:=Section.UsesClause;
|
||||
for i:=0 to length(UsesClause)-1 do
|
||||
begin
|
||||
if TObject(UsesList[i]) is TPasModule then
|
||||
if UsesClause[i].Module is TPasModule then
|
||||
begin
|
||||
UsedModule:=TPasModule(UsesList[i]);
|
||||
UsedModule:=TPasModule(UsesClause[i].Module);
|
||||
if CompareText(UsedModule.Name,'system')=0 then continue;
|
||||
if FindNode(UsedModule)=nil then
|
||||
EmitMessage(20170311191725,mtHint,nPAUnitNotUsed,sPAUnitNotUsed,
|
||||
|
@ -134,7 +134,7 @@ resourcestring
|
||||
type
|
||||
TPasScopeType = (
|
||||
stModule, // e.g. unit, program, library
|
||||
stUsesList,
|
||||
stUsesClause,
|
||||
stTypeSection,
|
||||
stTypeDef, // e.g. a TPasType
|
||||
stConstDef, // e.g. a TPasConst
|
||||
@ -312,7 +312,8 @@ type
|
||||
function DoParseExpression(AParent: TPaselement;InitExpr: TPasExpr=nil; AllowEqual : Boolean = True): TPasExpr;
|
||||
function DoParseConstValueExpression(AParent: TPasElement): TPasExpr;
|
||||
function CheckPackMode: TPackMode;
|
||||
function CheckUseUnit(ASection: TPasSection; AUnitName : string): TPasElement;
|
||||
function AddUseUnit(ASection: TPasSection; AUnitName : string;
|
||||
NameExpr: TPasExpr; InFileExpr: TPrimitiveExpr): TPasElement;
|
||||
procedure CheckImplicitUsedUnits(ASection: TPasSection);
|
||||
// Overload handling
|
||||
procedure AddProcOrFunction(Decs: TPasDeclarations; AProc: TPasProcedure);
|
||||
@ -2425,14 +2426,14 @@ begin
|
||||
end;
|
||||
|
||||
procedure TPasParser.ParseOptionalUsesList(ASection: TPasSection);
|
||||
// checks if next token is Uses keyword and read uses list
|
||||
// checks if next token is Uses keyword and reads the uses list
|
||||
begin
|
||||
NextToken;
|
||||
if CurToken=tkuses then
|
||||
ParseUsesList(ASection)
|
||||
else begin
|
||||
CheckImplicitUsedUnits(ASection);
|
||||
Engine.FinishScope(stUsesList,ASection);
|
||||
Engine.FinishScope(stUsesClause,ASection);
|
||||
UngetToken;
|
||||
end;
|
||||
end;
|
||||
@ -2852,38 +2853,64 @@ begin
|
||||
SetBlock(declNone);
|
||||
end;
|
||||
|
||||
function TPasParser.CheckUseUnit(ASection: TPasSection; AUnitName: string
|
||||
): TPasElement;
|
||||
function TPasParser.AddUseUnit(ASection: TPasSection; AUnitName: string;
|
||||
NameExpr: TPasExpr; InFileExpr: TPrimitiveExpr): TPasElement;
|
||||
|
||||
procedure CheckDuplicateInUsesList(AUnitName : string; UsesList: TFPList);
|
||||
procedure CheckDuplicateInUsesList(AUnitName : string; UsesClause: TPasUsesClause);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
if UsesList=nil then exit;
|
||||
for i:=0 to UsesList.Count-1 do
|
||||
if CompareText(AUnitName,TPasModule(UsesList[i]).Name)=0 then
|
||||
if UsesClause=nil then exit;
|
||||
for i:=0 to length(UsesClause)-1 do
|
||||
if CompareText(AUnitName,UsesClause[i].Name)=0 then
|
||||
ParseExc(nParserDuplicateIdentifier,SParserDuplicateIdentifier,[AUnitName]);
|
||||
end;
|
||||
|
||||
var
|
||||
UnitRef: TPasElement;
|
||||
begin
|
||||
if CompareText(AUnitName,CurModule.Name)=0 then
|
||||
begin
|
||||
// System is implicit, except when parsing system unit.
|
||||
if CompareText(AUnitName,'System')=0 then
|
||||
exit;
|
||||
ParseExc(nParserDuplicateIdentifier,SParserDuplicateIdentifier,[AUnitName]);
|
||||
end;
|
||||
CheckDuplicateInUsesList(AUnitName,ASection.UsesList);
|
||||
if ASection.ClassType=TImplementationSection then
|
||||
CheckDuplicateInUsesList(AUnitName,CurModule.InterfaceSection.UsesList);
|
||||
Result:=nil;
|
||||
try
|
||||
{$IFDEF VerbosePasParser}
|
||||
writeln('TPasParser.AddUseUnit AUnitName=',AUnitName,' CurModule.Name=',CurModule.Name);
|
||||
{$ENDIF}
|
||||
if CompareText(AUnitName,CurModule.Name)=0 then
|
||||
begin
|
||||
if CompareText(AUnitName,'System')=0 then
|
||||
exit; // for compatibility ignore implicit use of system in system
|
||||
ParseExc(nParserDuplicateIdentifier,SParserDuplicateIdentifier,[AUnitName]);
|
||||
end;
|
||||
CheckDuplicateInUsesList(AUnitName,ASection.UsesClause);
|
||||
if ASection.ClassType=TImplementationSection then
|
||||
CheckDuplicateInUsesList(AUnitName,CurModule.InterfaceSection.UsesClause);
|
||||
|
||||
result := Engine.FindModule(AUnitName); // should we resolve module here when "IN" filename is not known yet?
|
||||
if Assigned(result) then
|
||||
result.AddRef
|
||||
else
|
||||
Result := TPasUnresolvedUnitRef(CreateElement(TPasUnresolvedUnitRef,
|
||||
AUnitName, ASection));
|
||||
ASection.UsesList.Add(Result);
|
||||
UnitRef := Engine.FindModule(AUnitName); // should we resolve module here when "IN" filename is not known yet?
|
||||
if Assigned(UnitRef) then
|
||||
UnitRef.AddRef
|
||||
else
|
||||
UnitRef := TPasUnresolvedUnitRef(CreateElement(TPasUnresolvedUnitRef,
|
||||
AUnitName, ASection));
|
||||
|
||||
Result:=ASection.AddUnitToUsesList(AUnitName,NameExpr,InFileExpr,UnitRef);
|
||||
if InFileExpr<>nil then
|
||||
begin
|
||||
if UnitRef is TPasModule then
|
||||
begin
|
||||
if TPasModule(UnitRef).Filename='' then
|
||||
TPasModule(UnitRef).Filename:=InFileExpr.Value;
|
||||
end
|
||||
else if UnitRef is TPasUnresolvedUnitRef then
|
||||
TPasUnresolvedUnitRef(UnitRef).FileName:=InFileExpr.Value;
|
||||
end;
|
||||
finally
|
||||
if Result=nil then
|
||||
begin
|
||||
if NameExpr<>nil then
|
||||
NameExpr.Release;
|
||||
if InFileExpr<>nil then
|
||||
InFileExpr.Release;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TPasParser.CheckImplicitUsedUnits(ASection: TPasSection);
|
||||
@ -2894,43 +2921,60 @@ begin
|
||||
begin
|
||||
// load implicit units, like 'System'
|
||||
for i:=0 to ImplicitUses.Count-1 do
|
||||
CheckUseUnit(ASection,ImplicitUses[i]);
|
||||
AddUseUnit(ASection,ImplicitUses[i],nil,nil);
|
||||
end;
|
||||
end;
|
||||
|
||||
// Starts after the "uses" token
|
||||
procedure TPasParser.ParseUsesList(ASection: TPasSection);
|
||||
var
|
||||
AUnitName: String;
|
||||
Element: TPasElement;
|
||||
AUnitName, aName: String;
|
||||
NameExpr: TPasExpr;
|
||||
InFileExpr: TPrimitiveExpr;
|
||||
FreeExpr: Boolean;
|
||||
begin
|
||||
CheckImplicitUsedUnits(ASection);
|
||||
|
||||
Repeat
|
||||
AUnitName := ExpectIdentifier;
|
||||
NextToken;
|
||||
while CurToken = tkDot do
|
||||
begin
|
||||
ExpectIdentifier;
|
||||
AUnitName := AUnitName + '.' + CurTokenString;
|
||||
NameExpr:=nil;
|
||||
InFileExpr:=nil;
|
||||
FreeExpr:=true;
|
||||
try
|
||||
Repeat
|
||||
FreeExpr:=true;
|
||||
AUnitName := ExpectIdentifier;
|
||||
NameExpr:=CreatePrimitiveExpr(ASection,pekString,AUnitName);
|
||||
NextToken;
|
||||
end;
|
||||
Element := CheckUseUnit(ASection,AUnitName);
|
||||
if (CurToken=tkin) then
|
||||
while CurToken = tkDot do
|
||||
begin
|
||||
ExpectToken(tkString);
|
||||
if (Element is TPasModule) and (TPasmodule(Element).filename='') then
|
||||
TPasModule(Element).FileName:=curtokenstring
|
||||
else if (Element is TPasUnresolvedUnitRef) then
|
||||
TPasUnresolvedUnitRef(Element).FileName:=curtokenstring;
|
||||
NextToken;
|
||||
ExpectIdentifier;
|
||||
aName:=CurTokenString;
|
||||
AUnitName := AUnitName + '.' + aName;
|
||||
AddToBinaryExprChain(NameExpr,CreatePrimitiveExpr(ASection,pekString,aName),eopSubIdent);
|
||||
NextToken;
|
||||
end;
|
||||
if (CurToken=tkin) then
|
||||
begin
|
||||
ExpectToken(tkString);
|
||||
InFileExpr:=CreatePrimitiveExpr(ASection,pekString,CurTokenString);
|
||||
NextToken;
|
||||
end;
|
||||
FreeExpr:=false;
|
||||
AddUseUnit(ASection,AUnitName,NameExpr,InFileExpr);
|
||||
InFileExpr:=nil;
|
||||
NameExpr:=nil;
|
||||
|
||||
if Not (CurToken in [tkComma,tkSemicolon]) then
|
||||
ParseExc(nParserExpectedCommaSemicolon,SParserExpectedCommaSemicolon);
|
||||
Until (CurToken=tkSemicolon);
|
||||
if Not (CurToken in [tkComma,tkSemicolon]) then
|
||||
ParseExc(nParserExpectedCommaSemicolon,SParserExpectedCommaSemicolon);
|
||||
Until (CurToken=tkSemicolon);
|
||||
finally
|
||||
if FreeExpr then
|
||||
begin
|
||||
NameExpr.Release;
|
||||
InFileExpr.Release;
|
||||
end;
|
||||
end;
|
||||
|
||||
Engine.FinishScope(stUsesList,ASection);
|
||||
Engine.FinishScope(stUsesClause,ASection);
|
||||
end;
|
||||
|
||||
// Starts after the variable name
|
||||
|
@ -15,7 +15,7 @@ Type
|
||||
private
|
||||
function GetIf: TInterfaceSection;
|
||||
function GetIm: TImplementationSection;
|
||||
function CheckUnit(AIndex: Integer; const AName: String; AList: TFPList): TPasUnresolvedUnitRef;
|
||||
function CheckUnit(AIndex: Integer; const AName: String; Section: TPasSection): TPasUnresolvedUnitRef;
|
||||
Protected
|
||||
Procedure ParseUnit;
|
||||
Procedure ParseProgram;
|
||||
@ -98,18 +98,32 @@ begin
|
||||
end;
|
||||
|
||||
function TTestModuleParser.CheckUnit(AIndex: Integer; const AName: String;
|
||||
AList: TFPList) : TPasUnresolvedUnitRef;
|
||||
Section: TPasSection): TPasUnresolvedUnitRef;
|
||||
|
||||
Var
|
||||
C : string;
|
||||
AList: TFPList;
|
||||
Clause: TPasUsesClause;
|
||||
|
||||
begin
|
||||
Result:=nil;
|
||||
C:='Unit '+IntTostr(AIndex)+' ';
|
||||
|
||||
AList:=Section.UsesList;
|
||||
AssertNotNull('Have useslist',AList);
|
||||
if (AIndex>=AList.Count) then
|
||||
Fail(Format('Index %d larger than unit list count %d',[AIndex,AList.Count ]));
|
||||
AssertNotNull('Have pascal element',AList[AIndex]);
|
||||
AssertEquals(C+'Correct class',TPasUnresolvedUnitRef,TObject(AList[AIndex]).CLassType);
|
||||
Result:=TPasUnresolvedUnitRef(AList[AIndex]);
|
||||
|
||||
Clause:=Section.UsesClause;
|
||||
if AIndex>=length(Clause) then
|
||||
Fail(Format('Index %d larger than unit list count %d',[AIndex,length(Clause) ]));
|
||||
AssertNotNull('Have pascal element',Clause[AIndex]);
|
||||
AssertEquals(C+'Correct class',TPasUsesUnit,Clause[AIndex].ClassType);
|
||||
AssertNotNull(C+'Has Module',Clause[AIndex].Module);
|
||||
AssertEquals(C+'Correct module class',TPasUnresolvedUnitRef,Clause[AIndex].Module.ClassType);
|
||||
Result:=TPasUnresolvedUnitRef(Clause[AIndex].Module);
|
||||
AssertEquals(C+'Unit name correct',AName,Result.Name);
|
||||
end;
|
||||
|
||||
@ -119,8 +133,10 @@ begin
|
||||
StartImplementation;
|
||||
ParseUnit;
|
||||
AssertEquals('Only system in interface units',1,IntfSection.UsesList.Count);
|
||||
CheckUnit(0,'System',IntfSection.UsesList);
|
||||
AssertEquals('Only system in interface units',1,length(IntfSection.UsesClause));
|
||||
CheckUnit(0,'System',IntfSection);
|
||||
AssertEquals('No implementation units',0,ImplSection.UsesList.Count);
|
||||
AssertEquals('No implementation units',0,length(ImplSection.UsesClause));
|
||||
end;
|
||||
|
||||
procedure TTestModuleParser.TestUnitOneUses;
|
||||
@ -130,9 +146,11 @@ begin
|
||||
StartImplementation;
|
||||
ParseUnit;
|
||||
AssertEquals('Two interface units',2,IntfSection.UsesList.Count);
|
||||
CheckUnit(0,'System',IntfSection.UsesList);
|
||||
CheckUnit(1,'a',IntfSection.UsesList);
|
||||
AssertEquals('Two interface units',2,length(IntfSection.UsesClause));
|
||||
CheckUnit(0,'System',IntfSection);
|
||||
CheckUnit(1,'a',IntfSection);
|
||||
AssertEquals('No implementation units',0,ImplSection.UsesList.Count);
|
||||
AssertEquals('No implementation units',0,length(ImplSection.UsesClause));
|
||||
end;
|
||||
|
||||
procedure TTestModuleParser.TestUnitTwoUses;
|
||||
@ -141,11 +159,13 @@ begin
|
||||
UsesClause(['a','b']);
|
||||
StartImplementation;
|
||||
ParseUnit;
|
||||
AssertEquals('Two interface units',3,IntfSection.UsesList.Count);
|
||||
CheckUnit(0,'System',IntfSection.UsesList);
|
||||
CheckUnit(1,'a',IntfSection.UsesList);
|
||||
CheckUnit(2,'b',IntfSection.UsesList);
|
||||
AssertEquals('Three interface units',3,IntfSection.UsesList.Count);
|
||||
AssertEquals('Three interface units',3,length(IntfSection.UsesClause));
|
||||
CheckUnit(0,'System',IntfSection);
|
||||
CheckUnit(1,'a',IntfSection);
|
||||
CheckUnit(2,'b',IntfSection);
|
||||
AssertEquals('No implementation units',0,ImplSection.UsesList.Count);
|
||||
AssertEquals('No implementation units',0,length(ImplSection.UsesClause));
|
||||
end;
|
||||
|
||||
procedure TTestModuleParser.TestUnitOneImplUses;
|
||||
@ -155,9 +175,11 @@ begin
|
||||
UsesClause(['a']);
|
||||
ParseUnit;
|
||||
AssertEquals('One implementation units',1,ImplSection.UsesList.Count);
|
||||
CheckUnit(0,'a',ImplSection.UsesList);
|
||||
AssertEquals('One implementation units',1,length(ImplSection.UsesClause));
|
||||
CheckUnit(0,'a',ImplSection);
|
||||
AssertEquals('Only system in interface units',1,IntfSection.UsesList.Count);
|
||||
CheckUnit(0,'System',IntfSection.UsesList);
|
||||
AssertEquals('Only system in interface units',1,length(IntfSection.UsesClause));
|
||||
CheckUnit(0,'System',IntfSection);
|
||||
end;
|
||||
|
||||
procedure TTestModuleParser.TestUnitTwoImplUses;
|
||||
@ -167,10 +189,12 @@ begin
|
||||
UsesClause(['a','b']);
|
||||
ParseUnit;
|
||||
AssertEquals('One interface unit',1,IntfSection.UsesList.Count);
|
||||
CheckUnit(0,'System',IntfSection.UsesList);
|
||||
AssertEquals('One interface unit',1,length(IntfSection.UsesClause));
|
||||
CheckUnit(0,'System',IntfSection);
|
||||
AssertEquals('Two implementation units',2,ImplSection.UsesList.Count);
|
||||
CheckUnit(0,'a',ImplSection.UsesList);
|
||||
CheckUnit(1,'b',ImplSection.UsesList);
|
||||
AssertEquals('Two implementation units',2,length(ImplSection.UsesClause));
|
||||
CheckUnit(0,'a',ImplSection);
|
||||
CheckUnit(1,'b',ImplSection);
|
||||
end;
|
||||
|
||||
procedure TTestModuleParser.TestEmptyUnitInitialization;
|
||||
@ -260,8 +284,9 @@ begin
|
||||
Add('begin');
|
||||
ParseProgram;
|
||||
AssertEquals('Two interface units',2, PasProgram.ProgramSection.UsesList.Count);
|
||||
CheckUnit(0,'System',PasProgram.ProgramSection.UsesList);
|
||||
CheckUnit(1,'a',PasProgram.ProgramSection.UsesList);
|
||||
AssertEquals('Two interface units',2, length(PasProgram.ProgramSection.UsesClause));
|
||||
CheckUnit(0,'System',PasProgram.ProgramSection);
|
||||
CheckUnit(1,'a',PasProgram.ProgramSection);
|
||||
end;
|
||||
|
||||
procedure TTestModuleParser.TestEmptyProgramUsesTwoUnits;
|
||||
@ -270,9 +295,10 @@ begin
|
||||
Add('begin');
|
||||
ParseProgram;
|
||||
AssertEquals('Three interface units',3, PasProgram.ProgramSection.UsesList.Count);
|
||||
CheckUnit(0,'System',PasProgram.ProgramSection.UsesList);
|
||||
CheckUnit(1,'a',PasProgram.ProgramSection.UsesList);
|
||||
CheckUnit(2,'b',PasProgram.ProgramSection.UsesList);
|
||||
AssertEquals('Three interface unit',3, length(PasProgram.ProgramSection.UsesClause));
|
||||
CheckUnit(0,'System',PasProgram.ProgramSection);
|
||||
CheckUnit(1,'a',PasProgram.ProgramSection);
|
||||
CheckUnit(2,'b',PasProgram.ProgramSection);
|
||||
end;
|
||||
|
||||
procedure TTestModuleParser.TestEmptyProgramUsesUnitIn;
|
||||
@ -284,11 +310,12 @@ begin
|
||||
UsesClause(['a in ''../a.pas''','b']);
|
||||
Add('begin');
|
||||
ParseProgram;
|
||||
AssertEquals('One interface unit',3, PasProgram.ProgramSection.UsesList.Count);
|
||||
CheckUnit(0,'System',PasProgram.ProgramSection.UsesList);
|
||||
U:=CheckUnit(1,'a',PasProgram.ProgramSection.UsesList);
|
||||
AssertEquals('Three interface unit',3, PasProgram.ProgramSection.UsesList.Count);
|
||||
AssertEquals('Three interface unit',3, length(PasProgram.ProgramSection.UsesClause));
|
||||
CheckUnit(0,'System',PasProgram.ProgramSection);
|
||||
U:=CheckUnit(1,'a',PasProgram.ProgramSection);
|
||||
AssertEquals('Filename','''../a.pas''',U.FileName);
|
||||
CheckUnit(2,'b',PasProgram.ProgramSection.UsesList);
|
||||
CheckUnit(2,'b',PasProgram.ProgramSection);
|
||||
end;
|
||||
|
||||
procedure TTestModuleParser.TestEmptyLibrary;
|
||||
@ -305,8 +332,9 @@ begin
|
||||
ParseLibrary;
|
||||
AssertEquals('Correct class',TPasLibrary,Module.ClassType);
|
||||
AssertEquals('Two interface units',2, PasLibrary.LibrarySection.UsesList.Count);
|
||||
CheckUnit(0,'System',PasLibrary.LibrarySection.UsesList);
|
||||
CheckUnit(1,'a',PasLibrary.LibrarySection.UsesList);
|
||||
AssertEquals('Two interface units',2, length(PasLibrary.LibrarySection.UsesClause));
|
||||
CheckUnit(0,'System',PasLibrary.LibrarySection);
|
||||
CheckUnit(1,'a',PasLibrary.LibrarySection);
|
||||
end;
|
||||
|
||||
procedure TTestModuleParser.TestEmptyLibraryExports;
|
||||
|
@ -16,7 +16,7 @@ type
|
||||
FAnalyser : TPasSrcAnalysis;
|
||||
FSrc : TStrings;
|
||||
FList : TStrings;
|
||||
FStream: TmemoryStream;
|
||||
FStream: TMemoryStream;
|
||||
protected
|
||||
procedure SetUp; override;
|
||||
procedure TearDown; override;
|
||||
|
Loading…
Reference in New Issue
Block a user