Converter: Handle units in main and implementation uses sections separately. Includes patch from issue #17578.

git-svn-id: trunk@28062 -
This commit is contained in:
juha 2010-11-03 20:17:54 +00:00
parent 6a1f9c0370
commit c7e0f334c6
2 changed files with 69 additions and 59 deletions

View File

@ -58,6 +58,8 @@ type
fLowerCaseRes: boolean; fLowerCaseRes: boolean;
fDfmDirectiveStart: integer; fDfmDirectiveStart: integer;
fDfmDirectiveEnd: integer; fDfmDirectiveEnd: integer;
fExistingUsesMain: TStringList;
fExistingUsesImplementation: TStringList;
// List of units to remove. // List of units to remove.
fUnitsToRemove: TStringList; fUnitsToRemove: TStringList;
// Units to rename. Map of unit name -> real unit name. // Units to rename. Map of unit name -> real unit name.
@ -85,12 +87,13 @@ type
function FindApptypeConsole: boolean; function FindApptypeConsole: boolean;
function RemoveUnits: boolean; function RemoveUnits: boolean;
function RenameUnits: boolean; function RenameUnits: boolean;
function UsesSectionsToUnitnames: TStringList;
function FixMainClassAncestor(const AClassName: string; function FixMainClassAncestor(const AClassName: string;
AReplaceTypes: TStringToStringTree): boolean; AReplaceTypes: TStringToStringTree): boolean;
function CheckTopOffsets(LFMBuf: TCodeBuffer; LFMTree: TLFMTree; function CheckTopOffsets(LFMBuf: TCodeBuffer; LFMTree: TLFMTree;
VisOffsets: TVisualOffsets; ValueNodes: TObjectList): boolean; VisOffsets: TVisualOffsets; ValueNodes: TObjectList): boolean;
public public
property ExistingUsesMain: TStringList read fExistingUsesMain;
property ExistingUsesImplementation: TStringList read fExistingUsesImplementation;
property Ask: Boolean read fAsk write fAsk; property Ask: Boolean read fAsk write fAsk;
property HasFormFile: boolean read fHasFormFile write fHasFormFile; property HasFormFile: boolean read fHasFormFile write fHasFormFile;
property LowerCaseRes: boolean read fLowerCaseRes write fLowerCaseRes; property LowerCaseRes: boolean read fLowerCaseRes write fLowerCaseRes;
@ -106,6 +109,8 @@ implementation
{ TConvDelphiCodeTool } { TConvDelphiCodeTool }
constructor TConvDelphiCodeTool.Create(Code: TCodeBuffer); constructor TConvDelphiCodeTool.Create(Code: TCodeBuffer);
var
UsesNode: TCodeTreeNode;
begin begin
fCode:=Code; fCode:=Code;
// Default values for vars. // Default values for vars.
@ -114,12 +119,24 @@ begin
fUnitsToRemove:=nil; // These are set from outside. fUnitsToRemove:=nil; // These are set from outside.
fUnitsToComment:=nil; fUnitsToComment:=nil;
fUnitsToRename:=nil; fUnitsToRename:=nil;
fExistingUsesMain:=TStringList.Create;
fExistingUsesMain.CaseSensitive:=false;
fExistingUsesImplementation:=TStringList.Create;
fExistingUsesImplementation.CaseSensitive:=false;
// Initialize codetools. (Copied from TCodeToolManager.) // Initialize codetools. (Copied from TCodeToolManager.)
if not CodeToolBoss.InitCurCodeTool(fCode) then exit; if not CodeToolBoss.InitCurCodeTool(fCode) then exit;
try try
fCodeTool:=CodeToolBoss.CurCodeTool; fCodeTool:=CodeToolBoss.CurCodeTool;
fSrcCache:=CodeToolBoss.SourceChangeCache; fSrcCache:=CodeToolBoss.SourceChangeCache;
fSrcCache.MainScanner:=fCodeTool.Scanner; fSrcCache.MainScanner:=fCodeTool.Scanner;
// Get existing unit names from uses sections
fCodeTool.BuildTree(False);
UsesNode:=fCodeTool.FindMainUsesSection;
fExistingUsesMain:=TStringList(fCodeTool.UsesSectionToUnitnames(UsesNode));
fExistingUsesMain.Sorted:=True;
UsesNode:=fCodeTool.FindImplementationUsesSection;
fExistingUsesImplementation:=TStringList(fCodeTool.UsesSectionToUnitnames(UsesNode));
fExistingUsesImplementation.Sorted:=True;
except except
on e: Exception do on e: Exception do
CodeToolBoss.HandleException(e); CodeToolBoss.HandleException(e);
@ -128,6 +145,8 @@ end;
destructor TConvDelphiCodeTool.Destroy; destructor TConvDelphiCodeTool.Destroy;
begin begin
fExistingUsesImplementation.Free;
fExistingUsesMain.Free;
inherited Destroy; inherited Destroy;
end; end;
@ -209,46 +228,38 @@ end;
function TConvDelphiCodeTool.AddDelphiAndLCLSections: boolean; function TConvDelphiCodeTool.AddDelphiAndLCLSections: boolean;
// add, remove and rename units for desired target. // add, remove and rename units for desired target.
procedure RemoveUsesUnit(AUnitName: string);
var
UsesNode: TCodeTreeNode;
begin
fCodeTool.BuildTree(true);
UsesNode:=fCodeTool.FindMainUsesSection;
fCodeTool.MoveCursorToUsesStart(UsesNode);
fCodeTool.RemoveUnitFromUsesSection(UsesNode, UpperCaseStr(AUnitName), fSrcCache);
end;
var var
DelphiOnlyUnits: TStringList; // Delphi specific units. DelphiOnlyUnits: TStringList; // Delphi specific units.
LclOnlyUnits: TStringList; // LCL specific units. LclOnlyUnits: TStringList; // LCL specific units.
RenameList: TStringList; MainUsesNode, ImplementationUsesNode: TCodeTreeNode;
UsesNode: TCodeTreeNode;
s, nl: string; procedure ConvUsesUnits(AUsesNode: TCodeTreeNode; AUsesUnits: TStringList);
InsPos, i: Integer; var
begin i, ind: Integer;
Result:=false; InsPos: Integer;
DelphiOnlyUnits:=TStringList.Create; nl: string;
LclOnlyUnits:=TStringList.Create; s: string;
try RenameList: TStringList;
fCodeTool.BuildTree(true); begin
fSrcCache.MainScanner:=fCodeTool.Scanner; DelphiOnlyUnits.Clear;
UsesNode:=fCodeTool.FindMainUsesSection; LCLOnlyUnits.Clear;
if UsesNode<>nil then begin fCodeTool.MoveCursorToUsesStart(AUsesNode);
fCodeTool.MoveCursorToUsesStart(UsesNode);
InsPos:=fCodeTool.CurPos.StartPos; InsPos:=fCodeTool.CurPos.StartPos;
// Don't remove the unit names but add to Delphi block instead. // Don't remove the unit names but add to Delphi block instead.
for i:=0 to fUnitsToRemove.Count-1 do begin for i:=0 to fUnitsToRemove.Count-1 do begin
s:=fUnitsToRemove[i]; s:=fUnitsToRemove[i];
RemoveUsesUnit(s); if AUsesUnits.Find(s, ind) then begin // if RemoveUsesUnit(AUsesNode, s) then
DelphiOnlyUnits.Append(s); fCodeTool.RemoveUnitFromUsesSection(AUsesNode, UpperCaseStr(s), fSrcCache);
DelphiOnlyUnits.Append(s);
end;
end; end;
// ... and don't comment the unit names either. // ... and don't comment the unit names either.
for i:=0 to fUnitsToComment.Count-1 do begin for i:=0 to fUnitsToComment.Count-1 do begin
s:=fUnitsToComment[i]; s:=fUnitsToComment[i];
RemoveUsesUnit(s); if AUsesUnits.Find(s, ind) then begin // if RemoveUsesUnit(AUsesNode, s) then
DelphiOnlyUnits.Append(s); fCodeTool.RemoveUnitFromUsesSection(AUsesNode, UpperCaseStr(s), fSrcCache);
DelphiOnlyUnits.Append(s);
end;
end; end;
RenameList:=TStringList.Create; RenameList:=TStringList.Create;
try try
@ -256,13 +267,17 @@ begin
fUnitsToRename.GetNames(RenameList); fUnitsToRename.GetNames(RenameList);
for i:=0 to RenameList.Count-1 do begin for i:=0 to RenameList.Count-1 do begin
s:=RenameList[i]; s:=RenameList[i];
RemoveUsesUnit(s); if AUsesUnits.Find(s, ind) then begin // if RemoveUsesUnit(AUsesNode, s) then begin
DelphiOnlyUnits.Append(s); fCodeTool.RemoveUnitFromUsesSection(AUsesNode, UpperCaseStr(s), fSrcCache);
LclOnlyUnits.Append(fUnitsToRename[s]); DelphiOnlyUnits.Append(s);
LCLOnlyUnits.Append(fUnitsToRename[s]);
end;
end; end;
finally finally
RenameList.Free; RenameList.Free;
end; end;
{ TODO : handling of one used unit in one line is not functional yet
ex: uses consts;}
if (LclOnlyUnits.Count>0) or (DelphiOnlyUnits.Count>0) then begin if (LclOnlyUnits.Count>0) or (DelphiOnlyUnits.Count>0) then begin
// Add LCL and Delphi sections for output. // Add LCL and Delphi sections for output.
nl:=fSrcCache.BeautifyCodeOptions.LineEnd; nl:=fSrcCache.BeautifyCodeOptions.LineEnd;
@ -277,7 +292,23 @@ begin
if not fSrcCache.Replace(gtEmptyLine,gtNewLine,InsPos,InsPos,s) then exit; if not fSrcCache.Replace(gtEmptyLine,gtNewLine,InsPos,InsPos,s) then exit;
end; end;
end; end;
Result:=true;
begin
Result:=false;
DelphiOnlyUnits:=TStringList.Create;
LclOnlyUnits:=TStringList.Create;
try
fCodeTool.BuildTree(false);
fSrcCache.MainScanner:=fCodeTool.Scanner;
// Main uses section
MainUsesNode:=fCodeTool.FindMainUsesSection;
if MainUsesNode<>nil then
ConvUsesUnits(MainUsesNode, fExistingUsesMain);
// Implementation uses section
ImplementationUsesNode:=fCodeTool.FindImplementationUsesSection;
if ImplementationUsesNode<>nil then
ConvUsesUnits(ImplementationUsesNode, fExistingUsesImplementation);
Result:=true;
finally finally
LclOnlyUnits.Free; LclOnlyUnits.Free;
DelphiOnlyUnits.Free; DelphiOnlyUnits.Free;
@ -428,23 +459,6 @@ begin
Result:=true; Result:=true;
end; end;
function TConvDelphiCodeTool.UsesSectionsToUnitnames: TStringList;
// Collect all unit names from uses sections to a StringList.
var
UsesNode: TCodeTreeNode;
ImplList: TStrings;
begin
fCodeTool.BuildTree(true);
fSrcCache.MainScanner:=fCodeTool.Scanner;
UsesNode:=fCodeTool.FindMainUsesSection;
Result:=TStringList(fCodeTool.UsesSectionToUnitnames(UsesNode));
UsesNode:=fCodeTool.FindImplementationUsesSection;
ImplList:=fCodeTool.UsesSectionToUnitnames(UsesNode);
Result.AddStrings(ImplList);
ImplList.Free;
end;
function TConvDelphiCodeTool.FixMainClassAncestor(const AClassName: string; function TConvDelphiCodeTool.FixMainClassAncestor(const AClassName: string;
AReplaceTypes: TStringToStringTree): boolean; AReplaceTypes: TStringToStringTree): boolean;
// Replace the ancestor type of main form with a fall-back type if needed. // Replace the ancestor type of main form with a fall-back type if needed.

View File

@ -754,14 +754,16 @@ end;
function TConvertDelphiUnit.FixMissingUnits: TModalResult; function TConvertDelphiUnit.FixMissingUnits: TModalResult;
var var
UnitNames: TStringList; ConvTool: TConvDelphiCodeTool;
procedure RenameOrRemoveUnit(AOldName, ANewName: string); procedure RenameOrRemoveUnit(AOldName, ANewName: string);
// Replace a unit name with a new name or remove it if there is no new name. // Replace a unit name with a new name or remove it if there is no new name.
var var
x: Integer; x: Integer;
begin begin
if (ANewName<>'') and not UnitNames.Find(ANewName, x) then begin if (ANewName<>'')
and (not ConvTool.ExistingUsesMain.Find(ANewName, x))
and (not ConvTool.ExistingUsesImplementation.Find(ANewName, x)) then begin
fUnitsToRename[AOldName]:=ANewName; fUnitsToRename[AOldName]:=ANewName;
IDEMessagesWindow.AddMsg(Format( IDEMessagesWindow.AddMsg(Format(
'Replaced unit "%s" with "%s" in uses section.',[AOldName, ANewName]),'',-1); 'Replaced unit "%s" with "%s" in uses section.',[AOldName, ANewName]),'',-1);
@ -802,7 +804,6 @@ var
MapToEdit: TStringToStringTree; MapToEdit: TStringToStringTree;
Node: TAVLTreeNode; Node: TAVLTreeNode;
Item: PStringToStringTreeItem; Item: PStringToStringTreeItem;
ConvTool: TConvDelphiCodeTool;
i: Integer; i: Integer;
UnitN, s: string; UnitN, s: string;
begin begin
@ -811,15 +812,11 @@ begin
ConvTool:=TConvDelphiCodeTool.Create(fPascalBuffer); ConvTool:=TConvDelphiCodeTool.Create(fPascalBuffer);
if fSettings.UnitsReplaceMode=rlInteractive then if fSettings.UnitsReplaceMode=rlInteractive then
MapToEdit:=TStringToStringTree.Create(false); MapToEdit:=TStringToStringTree.Create(false);
UnitNames:=nil; // Will be created in ConvTool.UsesSectionsToUnitnames.
fMissingUnits:=nil; // Will be created in CodeToolBoss.FindMissingUnits. fMissingUnits:=nil; // Will be created in CodeToolBoss.FindMissingUnits.
try try
Result:=GetMissingUnits; Result:=GetMissingUnits;
if (Result<>mrOK) or (fMissingUnits=nil) or (fMissingUnits.Count=0) then exit; if (Result<>mrOK) or (fMissingUnits=nil) or (fMissingUnits.Count=0) then exit;
// Collect all unit names from uses sections.
UnitNames:=ConvTool.UsesSectionsToUnitnames;
UnitNames.Sorted:=true;
// Find replacements for missing units from settings. // Find replacements for missing units from settings.
for i:=fMissingUnits.Count-1 downto 0 do begin for i:=fMissingUnits.Count-1 downto 0 do begin
UnitN:=fMissingUnits[i]; UnitN:=fMissingUnits[i];
@ -874,7 +871,6 @@ begin
if fSettings.UnitsReplaceMode=rlInteractive then if fSettings.UnitsReplaceMode=rlInteractive then
MapToEdit.Free; MapToEdit.Free;
fMissingUnits.Free; fMissingUnits.Free;
UnitNames.Free;
ConvTool.Free; ConvTool.Free;
UnitUpdater.Free; UnitUpdater.Free;
end; end;