Browse Source

fcl-passrc: allow using unit twice with different alias

git-svn-id: trunk@43810 -
Mattias Gaertner 5 years ago
parent
commit
a3a67b13d8

+ 1 - 20
packages/fcl-passrc/src/pasresolver.pp

@@ -5676,7 +5676,7 @@ end;
 
 
 procedure TPasResolver.FinishUsesClause;
 procedure TPasResolver.FinishUsesClause;
 var
 var
-  Section, CurSection: TPasSection;
+  Section: TPasSection;
   i, j: Integer;
   i, j: Integer;
   PublicEl, UseModule: TPasElement;
   PublicEl, UseModule: TPasElement;
   Scope: TPasSectionScope;
   Scope: TPasSectionScope;
@@ -5723,25 +5723,6 @@ begin
         +UseUnit.Name+'->'+GetObjName(PublicEl)+'->'+PublicEl.CustomData.ClassName);
         +UseUnit.Name+'->'+GetObjName(PublicEl)+'->'+PublicEl.CustomData.ClassName);
     UsesScope:=TPasSectionScope(PublicEl.CustomData);
     UsesScope:=TPasSectionScope(PublicEl.CustomData);
 
 
-    // check if module was already used by a different name
-    j:=i;
-    CurSection:=Section;
-    repeat
-      dec(j);
-      if j<0 then
-        begin
-        if CurSection.ClassType<>TImplementationSection then
-          break;
-        CurSection:=CurSection.GetModule.InterfaceSection;
-        if CurSection=nil then break;
-        j:=length(CurSection.UsesClause)-1;
-        if j<0 then break;
-        end;
-      if CurSection.UsesClause[j].Module=UseModule then
-        RaiseMsg(20170503004022,nDuplicateIdentifier,sDuplicateIdentifier,
-          [UseModule.Name,GetElementSourcePosStr(CurSection.UsesClause[j])],UseUnit);
-    until false;
-
     // add full uses name
     // add full uses name
     AddIdentifier(Scope,UseUnit.Name,UseUnit,pikSimple);
     AddIdentifier(Scope,UseUnit.Name,UseUnit,pikSimple);
 
 

+ 7 - 21
packages/fcl-passrc/src/pparser.pp

@@ -3792,16 +3792,6 @@ function TPasParser.AddUseUnit(ASection: TPasSection;
         ParseExc(nParserDuplicateIdentifier,SParserDuplicateIdentifier,[AUnitName]);
         ParseExc(nParserDuplicateIdentifier,SParserDuplicateIdentifier,[AUnitName]);
   end;
   end;
 
 
-  procedure CheckDuplicateInUsesList(UnitRef: TPasElement; UsesClause: TPasUsesClause);
-  var
-    i: Integer;
-  begin
-    if UsesClause=nil then exit;
-    for i:=0 to length(UsesClause)-1 do
-      if UsesClause[i].Module=UnitRef then
-        ParseExc(nParserDuplicateIdentifier,SParserDuplicateIdentifier,[AUnitName]);
-  end;
-
 var
 var
   UnitRef: TPasElement;
   UnitRef: TPasElement;
   UsesUnit: TPasUsesUnit;
   UsesUnit: TPasUsesUnit;
@@ -3820,22 +3810,18 @@ begin
       ParseExc(nParserDuplicateIdentifier,SParserDuplicateIdentifier,[AUnitName]);
       ParseExc(nParserDuplicateIdentifier,SParserDuplicateIdentifier,[AUnitName]);
       end;
       end;
 
 
+    // Note: The alias (AUnitName) must be unique within a module.
+    //       Using an unit module twice with different alias is allowed.
+    CheckDuplicateInUsesList(ASection.UsesClause);
+    if ASection.ClassType=TImplementationSection then
+      CheckDuplicateInUsesList(CurModule.InterfaceSection.UsesClause);
+
     UnitRef := Engine.FindModule(AUnitName,NameExpr,InFileExpr);
     UnitRef := Engine.FindModule(AUnitName,NameExpr,InFileExpr);
     if Assigned(UnitRef) then
     if Assigned(UnitRef) then
-      begin
-      UnitRef.AddRef{$IFDEF CheckPasTreeRefCount}('TPasUsesUnit.Module'){$ENDIF};
-      CheckDuplicateInUsesList(UnitRef,ASection.UsesClause);
-      if ASection.ClassType=TImplementationSection then
-        CheckDuplicateInUsesList(UnitRef,CurModule.InterfaceSection.UsesClause);
-      end
+      UnitRef.AddRef{$IFDEF CheckPasTreeRefCount}('TPasUsesUnit.Module'){$ENDIF}
     else
     else
-      begin
-      CheckDuplicateInUsesList(ASection.UsesClause);
-      if ASection.ClassType=TImplementationSection then
-        CheckDuplicateInUsesList(CurModule.InterfaceSection.UsesClause);
       UnitRef := TPasUnresolvedUnitRef(CreateElement(TPasUnresolvedUnitRef,
       UnitRef := TPasUnresolvedUnitRef(CreateElement(TPasUnresolvedUnitRef,
         AUnitName, ASection, NamePos));
         AUnitName, ASection, NamePos));
-      end;
 
 
     UsesUnit:=TPasUsesUnit(CreateElement(TPasUsesUnit,AUnitName,ASection,NamePos));
     UsesUnit:=TPasUsesUnit(CreateElement(TPasUsesUnit,AUnitName,ASection,NamePos));
     Result:=ASection.AddUnitToUsesList(AUnitName,NameExpr,InFileExpr,UnitRef,UsesUnit);
     Result:=ASection.AddUnitToUsesList(AUnitName,NameExpr,InFileExpr,UnitRef,UsesUnit);

+ 3 - 4
packages/fcl-passrc/tests/tcresolver.pas

@@ -370,7 +370,7 @@ type
     Procedure TestUnit_DottedUnit;
     Procedure TestUnit_DottedUnit;
     Procedure TestUnit_DottedExpr;
     Procedure TestUnit_DottedExpr;
     Procedure TestUnit_DuplicateDottedUsesFail;
     Procedure TestUnit_DuplicateDottedUsesFail;
-    Procedure TestUnit_DuplicateUsesDiffNameFail;
+    Procedure TestUnit_DuplicateUsesDiffName;
     Procedure TestUnit_Unit1DotUnit2Fail;
     Procedure TestUnit_Unit1DotUnit2Fail;
     Procedure TestUnit_InFilename;
     Procedure TestUnit_InFilename;
     Procedure TestUnit_InFilenameAliasDelphiFail;
     Procedure TestUnit_InFilenameAliasDelphiFail;
@@ -5924,7 +5924,7 @@ begin
     nParserDuplicateIdentifier);
     nParserDuplicateIdentifier);
 end;
 end;
 
 
-procedure TTestResolver.TestUnit_DuplicateUsesDiffNameFail;
+procedure TTestResolver.TestUnit_DuplicateUsesDiffName;
 begin
 begin
   MainFilename:='unitdots.main1.pas';
   MainFilename:='unitdots.main1.pas';
   AddModuleWithIntfImplSrc('unitdots.unit1.pp',
   AddModuleWithIntfImplSrc('unitdots.unit1.pp',
@@ -5942,8 +5942,7 @@ begin
   '  if unit1.j1=0 then ;',
   '  if unit1.j1=0 then ;',
   '  if unitdots.unit1.j1=0 then ;',
   '  if unitdots.unit1.j1=0 then ;',
   '']);
   '']);
-  CheckParserException('Duplicate identifier "unit1" at token ";" in file unitdots.main1.pas at line 2 column 27',
-    nParserDuplicateIdentifier);
+  ParseProgram;
 end;
 end;
 
 
 procedure TTestResolver.TestUnit_Unit1DotUnit2Fail;
 procedure TTestResolver.TestUnit_Unit1DotUnit2Fail;

+ 52 - 0
packages/pastojs/tests/tcunitsearch.pas

@@ -145,10 +145,15 @@ type
     procedure TestUS_Program_FE_o;
     procedure TestUS_Program_FE_o;
     procedure TestUS_IncludeSameDir;
     procedure TestUS_IncludeSameDir;
 
 
+    // uses 'in' modifier
     procedure TestUS_UsesInFile;
     procedure TestUS_UsesInFile;
     procedure TestUS_UsesInFile_Duplicate;
     procedure TestUS_UsesInFile_Duplicate;
     procedure TestUS_UsesInFile_IndirectDuplicate;
     procedure TestUS_UsesInFile_IndirectDuplicate;
     procedure TestUS_UsesInFile_WorkNotEqProgDir;
     procedure TestUS_UsesInFile_WorkNotEqProgDir;
+    procedure TestUS_UsesInFileTwice;
+
+    procedure TestUS_UseUnitTwiceFail;
+    procedure TestUS_UseUnitTwiceViaNameSpace;
   end;
   end;
 
 
 function LinesToStr(const Lines: array of string): string;
 function LinesToStr(const Lines: array of string): string;
@@ -738,6 +743,7 @@ end;
 
 
 procedure TTestCLI_UnitSearch.TestUS_UsesInFile_Duplicate;
 procedure TTestCLI_UnitSearch.TestUS_UsesInFile_Duplicate;
 begin
 begin
+  // check if using two different units with same name
   AddUnit('system.pp',[''],['']);
   AddUnit('system.pp',[''],['']);
   AddUnit('unit1.pas',
   AddUnit('unit1.pas',
   ['var a: longint;'],
   ['var a: longint;'],
@@ -757,6 +763,7 @@ end;
 
 
 procedure TTestCLI_UnitSearch.TestUS_UsesInFile_IndirectDuplicate;
 procedure TTestCLI_UnitSearch.TestUS_UsesInFile_IndirectDuplicate;
 begin
 begin
+  // check if using two different units with same name
   AddUnit('system.pp',[''],['']);
   AddUnit('system.pp',[''],['']);
   AddUnit('unit1.pas',
   AddUnit('unit1.pas',
   ['var a: longint;'],
   ['var a: longint;'],
@@ -791,6 +798,51 @@ begin
   Compile(['sub/test1.pas','-Jc']);
   Compile(['sub/test1.pas','-Jc']);
 end;
 end;
 
 
+procedure TTestCLI_UnitSearch.TestUS_UsesInFileTwice;
+begin
+  AddUnit('system.pp',[''],['']);
+  AddUnit('unit1.pas',
+  ['var a: longint;'],
+  ['']);
+  AddFile('test1.pas',[
+    'uses foo in ''unit1.pas'', bar in ''unit1.pas'';',
+    'begin',
+    '  bar.a:=foo.a;',
+    '  a:=a;',
+    'end.']);
+  Compile(['test1.pas','-Jc']);
+end;
+
+procedure TTestCLI_UnitSearch.TestUS_UseUnitTwiceFail;
+begin
+  AddUnit('system.pp',[''],['']);
+  AddUnit('sub.unit1.pas',
+  ['var a: longint;'],
+  ['']);
+  AddFile('test1.pas',[
+    'uses sub.Unit1, sub.unit1;',
+    'begin',
+    '  a:=a;',
+    'end.']);
+  Compile(['test1.pas','-FNsub','-Jc'],ExitCodeSyntaxError);
+  AssertEquals('ErrorMsg','Duplicate identifier "sub.unit1"',ErrorMsg);
+end;
+
+procedure TTestCLI_UnitSearch.TestUS_UseUnitTwiceViaNameSpace;
+begin
+  AddUnit('system.pp',[''],['']);
+  AddUnit('sub.unit1.pas',
+  ['var a: longint;'],
+  ['']);
+  AddFile('test1.pas',[
+    'uses unit1, sub.unit1;',
+    'begin',
+    '  unit1.a:=sub.unit1.a;',
+    '  a:=a;',
+    'end.']);
+  Compile(['test1.pas','-FNsub','-Jc']);
+end;
+
 Initialization
 Initialization
   RegisterTests([TTestCLI_UnitSearch]);
   RegisterTests([TTestCLI_UnitSearch]);
 end.
 end.