{******************************************************************************}
{                                                                              }
{                       Pascal Script Source File                              }
{                                                                              }
{             Run by RemObjects Pascal Script in CnPack IDE Wizards            }
{                                                                              }
{                                   Generated by CnPack IDE Wizards            }
{                                                                              }
{******************************************************************************}

program UsesInitTree;

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ActnList, Buttons, ClipBrd, ComCtrls, ExtCtrls, ComObj, ExtDlgs, IniFiles,
  Menus, Printers, Registry, StdCtrls, TypInfo, ToolsAPI, CnDebug,
  RegExpr, ScriptEvent, CnCommon, CnWizClasses, CnWizUtils, CnWizIdeUtils,
  CnWizShortCut, CnWizOptions;

  // If need to access IDE Components, please uses IdeInstComp

// 采用分析 Pascal 源码的方式对当前工程进行引用分析，打印出各单元的初始化树顺序
// 注意由于可能存在编译指令的情况，分析源码所得到的结果和实际情况不一定相同

procedure SearchAUnit(const AFullUnitName: string; ProcessedFiles: TStrings;
  Level: Integer; AProject: IOTAProject);
var
  St: TCnModuleSearchType;
  AFileName, S: string;
  UsesList: TStringList;
  I: Integer;
begin
  if AFullUnitName = '' then
    Exit;

  UsesList := TStringList.Create;
  try
    ParseUnitUsesFromFileName(AFullUnitName, UsesList);

    for I := 0 to UsesList.Count - 1 do
    begin
      AFileName := GetFileNameSearchTypeFromModuleName(UsesList[I], St, AProject);
      if (AFileName = '') or (ProcessedFiles.IndexOf(AFileName) >= 0) then
        Continue;

      // AFileName 存在且未处理过，就打印
      ProcessedFiles.Add(AFileName);

      S := StringOfChar('-', Level) + ' ' + AFileName;
      case St of
        mstProject: S := S + ' | (In Project)';
        mstProjectSearch: S := S + ' | (In Project Search Path)';
        mstSystemSearch: S := S + ' | (In System Path)';
      end;

      if UsesList.Objects[I] <> nil then
        S := S + ' | impl';
      Writeln(S);

      SearchAUnit(AFileName, ProcessedFiles, Level + 1, AProject);
    end;
  finally
    UsesList.Free;
  end;
end;

var
  Proj: IOTAProject;
  FileNames: TStringList;
begin
  Proj := CnOtaGetCurrentProject;
  if (Proj = nil) or not IsDelphiProject(Proj) then
    Exit;

  FileNames := TStringList.Create;
  try
    SearchAUnit(CnOtaGetProjectSourceFileName(Proj), FileNames, 1, Proj);
  finally
    FileNames.Free;
  end;
end.
 
