فهرست منبع

fcl-passrc: parser: create usesclause

git-svn-id: trunk@36006 -
Mattias Gaertner 8 سال پیش
والد
کامیت
d7163d3854

+ 31 - 22
packages/fcl-passrc/src/pasresolver.pp

@@ -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

+ 1 - 1
packages/fcl-passrc/src/passrcutil.pp

@@ -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);

+ 20 - 8
packages/fcl-passrc/src/pastree.pp

@@ -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;

+ 10 - 10
packages/fcl-passrc/src/pasuseanalyzer.pas

@@ -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,

+ 95 - 51
packages/fcl-passrc/src/pparser.pp

@@ -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);
+  finally
+    if FreeExpr then
+      begin
+      NameExpr.Release;
+      InFileExpr.Release;
+      end;
+  end;
 
-    if Not (CurToken in [tkComma,tkSemicolon]) then
-      ParseExc(nParserExpectedCommaSemicolon,SParserExpectedCommaSemicolon);
-  Until (CurToken=tkSemicolon);
-
-  Engine.FinishScope(stUsesList,ASection);
+  Engine.FinishScope(stUsesClause,ASection);
 end;
 
 // Starts after the variable name

+ 54 - 26
packages/fcl-passrc/tests/tcmoduleparser.pas

@@ -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;

+ 1 - 1
packages/fcl-passrc/tests/tcpassrcutil.pas

@@ -16,7 +16,7 @@ type
     FAnalyser : TPasSrcAnalysis;
     FSrc : TStrings;
     FList : TStrings;
-    FStream: TmemoryStream;
+    FStream: TMemoryStream;
   protected
     procedure SetUp; override;
     procedure TearDown; override;