unit IDEUtils.JSONDescendantClassesBuilder;

interface

uses
  System.Classes, IDEUtils.JSONDescendantClassesCommon;

procedure ParseJSONUnit(UnitInfo: TUnitInfo);

procedure BuildJSONDescendantClasses(UnitInfo: TUnitInfo);

implementation

uses
  System.SysUtils, Vcl.Dialogs, ToolsAPI;

type
  TCreator = class(TInterfacedObject, IOTACreator, IOTAModuleCreator)
  private
    FSource: string;
  public
    constructor Create(ASource: string);
    { IOTAModuleCreator }
    function GetAncestorName: string;
    function GetImplFileName: string;
    function GetIntfFileName: string;
    function GetFormName: string;
    function GetMainForm: Boolean;
    function GetShowForm: Boolean;
    function GetShowSource: Boolean;
    function NewFormFile(const FormIdent, AncestorIdent: string): IOTAFile;
    function NewImplSource(const ModuleIdent, FormIdent, AncestorIdent: string)
      : IOTAFile;
    function NewIntfSource(const ModuleIdent, FormIdent, AncestorIdent: string)
      : IOTAFile;
    procedure FormCreated(const FormEditor: IOTAFormEditor);
    { IOTACreator }
    function GetCreatorType: string;
    function GetExisting: Boolean;
    function GetFileSystem: string;
    function GetOwner: IOTAModule;
    function GetUnnamed: Boolean;
  end;

  TFile = class(TInterfacedObject, IOTAFile)
  private
    FSource: string;
  public
    constructor Create(const Source: string);
    function GetSource: string;
    function GetAge: TDateTime;
  end;

  PStringList = ^TStringList;

procedure GetLine(ALine: Longint; ALineInfo: POTALineInfo; AUserData: Pointer);
{$IFDEF WIN32} pascal {$ENDIF}
begin
  PStringList(AUserData).Add(copy(UTF8ToString(ALineInfo.lineText), 1,
    ALineInfo.lineLength));
end;

procedure ParseJSONUnit(UnitInfo: TUnitInfo);
var
  i: Integer;
  EditorServices: IOTAEditorServices;
  EditBufferIterator: IOTAEditBufferIterator;
  EditBuffer: IOTAEditBuffer;
  RawReader: IOTARawEditReader;
  sl: TStringList;
begin
  sl := TStringList.Create;
  try
    if Supports(BorlandIDEServices, IOTAEditorServices, EditorServices) and
      EditorServices.GetEditBufferIterator(EditBufferIterator) then
    begin
      for i := 0 to EditBufferIterator.Count - 1 do
      begin
        EditBuffer := EditBufferIterator.EditBuffers[i];
        if EditBuffer.FileName = UnitInfo.ProjectFileName then
        begin
          if Supports(EditBuffer, IOTARawEditReader, RawReader) then
            RawReader.GetLineData(1, MaxInt, GetLine, @sl);
          break;
        end;
      end;
    end;
    if (sl.Count = 0) and FileExists(UnitInfo.ProjectFileName) then
      sl.LoadFromFile(UnitInfo.ProjectFileName);
    if sl.Count = 0 then
    begin
      ShowMessage(UnitInfo.UnitName + ' (' + UnitInfo.ProjectFileName +
        ') not found.');
      exit;
    end;
    GatherUnitInfo(sl, UnitInfo);
  finally
    sl.Free;
  end;
end;

procedure BuildJSONDescendantClasses(UnitInfo: TUnitInfo);
const
  Comment1Const =
    '// Although this unit has been autogenerated, it is intended to be modified.';
  Comment2Const = '// Source %s, Date: %s';

var
  sl: TStringList;
  ModuleServices: IOTAModuleServices;
  BUnitIdent, BClassName, BFileName, DateText: string;

begin
  if Supports(BorlandIDEServices, IOTAModuleServices, ModuleServices) then
  begin
    sl := TStringList.Create;
    try
      BuildDescendantUnit(sl, UnitInfo);
      ModuleServices.GetNewModuleAndClassName(sUnit, BUnitIdent, BClassName,
        BFileName);
      sl.Insert(0, Comment1Const);
      DateTimeToString(DateText, '', now);
      sl.Insert(1, Format(Comment2Const, [UnitInfo.ProjectUnitName, DateText]));
      sl.Insert(2, '');
      sl.Insert(3, 'unit ' + BUnitIdent + ';');
      ModuleServices.CreateModule(TCreator.Create(sl.Text));
    finally
      sl.Free;
    end;
  end;
end;

{ TCreator }

constructor TCreator.Create(ASource: string);
begin
  inherited Create;
  FSource := ASource;
end;

procedure TCreator.FormCreated(const FormEditor: IOTAFormEditor);
begin

end;

function TCreator.GetAncestorName: string;
begin
  Result := '';
end;

function TCreator.GetCreatorType: string;
begin
  Result := sUnit;
end;

function TCreator.GetExisting: Boolean;
begin
  Result := False;
end;

function TCreator.GetFileSystem: string;
begin
  Result := '';
end;

function TCreator.GetFormName: string;
begin
  Result := '';
end;

function TCreator.GetImplFileName: string;
begin
  Result := '';
end;

function TCreator.GetIntfFileName: string;
begin
  Result := '';
end;

function TCreator.GetMainForm: Boolean;
begin
  Result := False;
end;

function TCreator.GetOwner: IOTAModule;
begin
  Result := (BorlandIDEServices as IOTAModuleServices).GetActiveProject;
end;

function TCreator.GetShowForm: Boolean;
begin
  Result := False;
end;

function TCreator.GetShowSource: Boolean;
begin
  Result := True;
end;

function TCreator.GetUnnamed: Boolean;
begin
  Result := True;
end;

function TCreator.NewFormFile(const FormIdent, AncestorIdent: string): IOTAFile;
begin
  Result := nil;
end;

function TCreator.NewImplSource(const ModuleIdent, FormIdent,
  AncestorIdent: string): IOTAFile;
begin
  Result := TFile.Create(FSource);
end;

function TCreator.NewIntfSource(const ModuleIdent, FormIdent,
  AncestorIdent: string): IOTAFile;
begin
  Result := nil;
end;

constructor TFile.Create(const Source: string);
begin
  FSource := Source;
end;

function TFile.GetSource: string;
begin
  Result := FSource;
end;

function TFile.GetAge: TDateTime;
begin
  Result := TDateTime(-1);
end;

end.
