Jump to content

Dany Marmur

Members
  • Content Count

    877
  • Joined

  • Last visited

  • Days Won

    13

Posts posted by Dany Marmur


  1. Last time (so tired of all the IFDEFs for debug logging) i tried Assert. The basic idea of Assert is nice as (correct me if i'm wrong) the compiler does not produce any code for production. But it does not help with th issue of cluttered-up sources. Also it would be nice with a version of Assert that is a bit more flexible.

     

    @edwinyzh second idea seems most apt. In my mind it will not be a small project. But i have not used the full-blown tool for these things enough to have any constructive input.


  2. Yes, but a zip with an executable, then i have to code settings for the different names, i simply do not have the time now 😞.

    The three code-windows above is all the code except for the dpr! You can just copy paste it really.

     

    This is what i have for DWScript: https://xxx@bitbucket.org/egrange/dwscript.git

    This is the path to DWSJSON: https://github.com/masonwheeler/DFMJSON.git

     

    I suppose if one had the time you could VCL-ify it, add persistence and settings and some more and you'll have a neat contribution to the community.

    This was a very fast hack when i moved from my own dynamic SQL-repository to using DFMs. I missed the global searches i could do in my own repo.

     

    HTH,

     

    /D

     

     


  3. @David Schwartz, RTC is here https://rtc.teppi.net/ but as i said - i only used its JSON parsing classes (value handling). You should be able to snappily change it to what comes with Delphi.

    Since you have DX, here's the complete visual code. Now i have pasted the whole project 🙂

    BTW - you noticed my DACs are IBO, you have to change names to whatever you use.

     

    unit Forms.MainForm;
    
    interface
    
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, cxGraphics, cxControls, cxLookAndFeels, cxLookAndFeelPainters, cxContainer,
      cxEdit, dxLayoutcxEditAdapters, dxLayoutContainer, cxStyles, cxCustomData, cxFilter, cxData, cxDataStorage,
      cxNavigator, cxDataControllerConditionalFormattingRulesManagerDialog, cxMemo, cxGridCustomTableView, cxGridTableView,
      cxGridCustomView, cxClasses, cxGridLevel, cxGrid, cxTextEdit, cxMaskEdit, cxButtonEdit, dxLayoutControl,
      cxCustomListBox, cxListBox, cxCheckBox, cxGridWinExplorerView, dxBarBuiltInMenu, cxGridCustomPopupMenu,
      cxGridPopupMenu, dxLayoutControlAdapters, Vcl.Menus, Vcl.StdCtrls, cxButtons, dxSkinsCore, dxSkinOffice2013White,
      dxLayoutLookAndFeels;
    
    type
      TCollectorMainForm = class(TForm)
        LayoutControlMainGroup_Root: TdxLayoutGroup;
        LayoutControlMain: TdxLayoutControl;
        SQLGridLevel: TcxGridLevel;
        SQLGrid: TcxGrid;
        dxLayoutItem2: TdxLayoutItem;
        SQLTableView: TcxGridTableView;
        SQLTableViewColumnFormName: TcxGridColumn;
        SQLTableViewColumnStmtClass: TcxGridColumn;
        SQLTableViewColumnStmtName: TcxGridColumn;
        SQLTableViewColumnSQLText: TcxGridColumn;
        LogListBox: TcxListBox;
        dxLayoutItem3: TdxLayoutItem;
        FullRowHeightCheckBox: TcxCheckBox;
        dxLayoutItem4: TdxLayoutItem;
        SQLTableViewColumnStoredProcName: TcxGridColumn;
        SQLGridPopupMenu: TcxGridPopupMenu;
        PathTextEdit: TcxTextEdit;
        dxLayoutItem1: TdxLayoutItem;
        ScanButton: TcxButton;
        dxLayoutItem5: TdxLayoutItem;
        dxLayoutAutoCreatedGroup1: TdxLayoutAutoCreatedGroup;
        SQLStyleRepository: TcxStyleRepository;
        cxStyle1: TcxStyle;
        dxLayoutGroup1: TdxLayoutGroup;
        dxLayoutLookAndFeelList1: TdxLayoutLookAndFeelList;
        dxLayoutCxLookAndFeel1: TdxLayoutCxLookAndFeel;
        procedure cxCheckBox1PropertiesChange(Sender: TObject);
        procedure ScanButtonClick(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        procedure RefreshGrid;
      public
        { Public declarations }
      end;
    
    var
      CollectorMainForm: TCollectorMainForm;
    
    implementation
    
    uses
      Data.ObjectCollector;
    
    {$R *.dfm}
    
    procedure TCollectorMainForm.ScanButtonClick(Sender: TObject);
    begin
      RefreshGrid;
    end;
    
    procedure TCollectorMainForm.cxCheckBox1PropertiesChange(Sender: TObject);
    begin
      SQLTableView.OptionsView.CellAutoHeight := FullRowHeightCheckBox.Checked;
      if FullRowHeightCheckBox.Checked then
        SQLTableView.Controller.TopRowIndex := SQLTableView.Controller.FocusedRowIndex;
    end;
    
    procedure TCollectorMainForm.FormCreate(Sender: TObject);
    begin
      RefreshGrid;
      SQLTableView.Controller.ShowFindPanel;
    end;
    
    procedure TCollectorMainForm.RefreshGrid;
    var
      lCurrent: Integer;
    begin
      lCurrent := 1;
      SQLTableView.DataController.BeginUpdate;
      LogListBox.Items.BeginUpdate;
      try
        LogListBox.Items.Clear;
        SQLTableView.DataController.RecordCount := 0;
    
        Data.ObjectCollector.ObjectCollectoDataModule.RunCollect(
          PathTextEdit.Text, '*.dfm', false,
          procedure (aStatementInfo: TStatementInfo)
          begin
            SQLTableView.DataController.RecordCount := lCurrent;
            SQLTableView.DataController.Values[lCurrent - 1, SQLTableViewColumnFormName.Index]        := aStatementInfo.FormName;
            SQLTableView.DataController.Values[lCurrent - 1, SQLTableViewColumnStmtClass.Index]       := aStatementInfo.StatementClass;
            SQLTableView.DataController.Values[lCurrent - 1, SQLTableViewColumnStmtName.Index]        := aStatementInfo.StatementName;
            SQLTableView.DataController.Values[lCurrent - 1, SQLTableViewColumnStoredProcName.Index]  := aStatementInfo.StoredProcName;
            SQLTableView.DataController.Values[lCurrent - 1, SQLTableViewColumnSQLText.Index]         := aStatementInfo.StatementSQL;
            Inc(lCurrent);
          end,
          procedure (aText: string)
          begin
            LogListBox.Items.Append(aText);
          end,
          procedure (aText: string)
          begin
            LogListBox.Items.Append(aText);
          end);
    
          LogListBox.ItemIndex := LogListBox.Items.Count - 1;
      finally
        LogListBox.Items.EndUpdate;
        SQLTableView.DataController.EndUpdate;
      end;
    end;
    
    end.

    ... and the dfm ...

     

    object CollectorMainForm: TCollectorMainForm
      Left = 0
      Top = 0
      ActiveControl = SQLGrid
      Caption = 'DFM SQL Collector'
      ClientHeight = 892
      ClientWidth = 1507
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      OldCreateOrder = False
      OnCreate = FormCreate
      PixelsPerInch = 96
      TextHeight = 13
      object LayoutControlMain: TdxLayoutControl
        Left = 0
        Top = 0
        Width = 1507
        Height = 892
        Align = alClient
        TabOrder = 0
        LayoutLookAndFeel = dxLayoutCxLookAndFeel1
        HighlightRoot = False
        object SQLGrid: TcxGrid
          Left = 10
          Top = 55
          Width = 1487
          Height = 793
          TabOrder = 3
          object SQLTableView: TcxGridTableView
            Navigator.Buttons.CustomButtons = <>
            Navigator.Buttons.First.Visible = True
            Navigator.Buttons.PriorPage.Visible = True
            Navigator.Buttons.Prior.Visible = True
            Navigator.Buttons.Next.Visible = True
            Navigator.Buttons.NextPage.Visible = True
            Navigator.Buttons.Last.Visible = True
            Navigator.Buttons.Insert.Visible = False
            Navigator.Buttons.Append.Visible = False
            Navigator.Buttons.Delete.Visible = False
            Navigator.Buttons.Edit.Visible = False
            Navigator.Buttons.Post.Visible = False
            Navigator.Buttons.Cancel.Visible = False
            Navigator.Buttons.Refresh.Visible = False
            Navigator.Buttons.SaveBookmark.Visible = True
            Navigator.Buttons.GotoBookmark.Visible = True
            Navigator.Buttons.Filter.Visible = True
            Navigator.InfoPanel.Visible = True
            Navigator.Visible = True
            FindPanel.DisplayMode = fpdmManual
            DataController.Options = [dcoCaseInsensitive, dcoAssignGroupingValues, dcoAssignMasterDetailKeys, dcoSaveExpanding]
            DataController.Summary.DefaultGroupSummaryItems = <>
            DataController.Summary.FooterSummaryItems = <>
            DataController.Summary.SummaryGroups = <>
            FixedDataRows.PinVisibility = rpvRowHotTrack
            OptionsBehavior.CopyCaptionsToClipboard = False
            OptionsBehavior.FocusCellOnTab = True
            OptionsBehavior.IncSearch = True
            OptionsBehavior.NavigatorHints = True
            OptionsBehavior.RecordScrollMode = rsmByPixel
            OptionsCustomize.ColumnHiding = True
            OptionsCustomize.ColumnHidingOnGrouping = False
            OptionsCustomize.ColumnsQuickCustomization = True
            OptionsCustomize.DataRowFixing = True
            OptionsData.Deleting = False
            OptionsData.Inserting = False
            OptionsView.CellAutoHeight = True
            OptionsView.ColumnAutoWidth = True
            OptionsView.HeaderEndEllipsis = True
            OptionsView.HeaderFilterButtonShowMode = fbmSmartTag
            OptionsView.Indicator = True
            OptionsView.ShowColumnFilterButtons = sfbWhenSelected
            Styles.Background = cxStyle1
            Styles.Content = cxStyle1
            Styles.ContentEven = cxStyle1
            Styles.ContentOdd = cxStyle1
            Styles.FilterBox = cxStyle1
            Styles.FindPanel = cxStyle1
            Styles.IncSearch = cxStyle1
            Styles.Navigator = cxStyle1
            Styles.NavigatorInfoPanel = cxStyle1
            Styles.SearchResultHighlight = cxStyle1
            Styles.FilterRowInfoText = cxStyle1
            Styles.Footer = cxStyle1
            Styles.Group = cxStyle1
            Styles.GroupByBox = cxStyle1
            Styles.GroupFooterSortedSummary = cxStyle1
            Styles.GroupSortedSummary = cxStyle1
            Styles.GroupSummary = cxStyle1
            Styles.Header = cxStyle1
            Styles.Inactive = cxStyle1
            Styles.Indicator = cxStyle1
            Styles.InplaceEditFormGroup = cxStyle1
            Styles.InplaceEditFormItem = cxStyle1
            Styles.InplaceEditFormItemHotTrack = cxStyle1
            Styles.NewItemRowInfoText = cxStyle1
            Styles.Preview = cxStyle1
            Styles.Selection = cxStyle1
            object SQLTableViewColumnFormName: TcxGridColumn
              Caption = 'Form Name'
              PropertiesClassName = 'TcxTextEditProperties'
              Properties.ReadOnly = True
              Options.FilteringPopupIncrementalFiltering = True
              Width = 165
            end
            object SQLTableViewColumnStmtClass: TcxGridColumn
              Caption = 'Statement Class'
              PropertiesClassName = 'TcxTextEditProperties'
              Properties.ReadOnly = True
              Options.FilteringPopupIncrementalFiltering = True
              Width = 110
            end
            object SQLTableViewColumnStmtName: TcxGridColumn
              Caption = 'Statement Name'
              PropertiesClassName = 'TcxTextEditProperties'
              Properties.ReadOnly = True
              Options.FilteringPopupIncrementalFiltering = True
              SortIndex = 0
              SortOrder = soAscending
              Width = 152
            end
            object SQLTableViewColumnStoredProcName: TcxGridColumn
              Caption = 'Stored Proc Name'
              PropertiesClassName = 'TcxTextEditProperties'
              Options.FilteringPopupIncrementalFiltering = True
              Width = 110
            end
            object SQLTableViewColumnSQLText: TcxGridColumn
              Caption = 'SQL Text'
              PropertiesClassName = 'TcxMemoProperties'
              Properties.ReadOnly = True
              Properties.ScrollBars = ssVertical
              Options.FilteringPopupIncrementalFiltering = True
              Width = 739
            end
          end
          object SQLGridLevel: TcxGridLevel
            GridView = SQLTableView
          end
        end
        object LogListBox: TcxListBox
          Left = 10000
          Top = 10000
          Width = 1467
          Height = 63
          ItemHeight = 13
          TabOrder = 4
          Visible = False
        end
        object FullRowHeightCheckBox: TcxCheckBox
          Left = 1405
          Top = 11
          Caption = 'Full row height'
          Properties.OnChange = cxCheckBox1PropertiesChange
          State = cbsChecked
          Style.HotTrack = False
          Style.Shadow = False
          Style.TransparentBorder = True
          TabOrder = 2
          Transparent = True
        end
        object PathTextEdit: TcxTextEdit
          Left = 37
          Top = 10
          Style.HotTrack = False
          TabOrder = 0
          Text = 'C:\Users\Superkey\Documents\Projects'
          TextHint = 'All *.dfm files in the path will be searched'
          Width = 1281
        end
        object ScanButton: TcxButton
          Left = 1324
          Top = 10
          Width = 75
          Height = 21
          Caption = 'SCAN'
          Default = True
          SpeedButtonOptions.CanBeFocused = False
          TabOrder = 1
          OnClick = ScanButtonClick
        end
        object LayoutControlMainGroup_Root: TdxLayoutGroup
          AlignHorz = ahClient
          AlignVert = avClient
          ButtonOptions.Buttons = <>
          Hidden = True
          ItemIndex = 2
          ShowBorder = False
          Index = -1
        end
        object dxLayoutItem2: TdxLayoutItem
          Parent = LayoutControlMainGroup_Root
          AlignVert = avClient
          CaptionOptions.Text = 'SQL Queries'
          CaptionOptions.Layout = clTop
          Control = SQLGrid
          ControlOptions.OriginalHeight = 200
          ControlOptions.OriginalWidth = 250
          ControlOptions.ShowBorder = False
          Index = 1
        end
        object dxLayoutItem3: TdxLayoutItem
          Parent = dxLayoutGroup1
          AlignVert = avClient
          CaptionOptions.Text = 'Log'
          CaptionOptions.Visible = False
          CaptionOptions.Layout = clTop
          Control = LogListBox
          ControlOptions.OriginalHeight = 97
          ControlOptions.OriginalWidth = 121
          ControlOptions.ShowBorder = False
          Index = 0
        end
        object dxLayoutItem4: TdxLayoutItem
          Parent = dxLayoutAutoCreatedGroup1
          AlignVert = avCenter
          CaptionOptions.Text = 'FullRowHeight'
          CaptionOptions.Visible = False
          Control = FullRowHeightCheckBox
          ControlOptions.OriginalHeight = 19
          ControlOptions.OriginalWidth = 92
          ControlOptions.ShowBorder = False
          Index = 2
        end
        object dxLayoutItem1: TdxLayoutItem
          Parent = dxLayoutAutoCreatedGroup1
          AlignHorz = ahClient
          AlignVert = avCenter
          CaptionOptions.Text = 'Path'
          Control = PathTextEdit
          ControlOptions.OriginalHeight = 21
          ControlOptions.OriginalWidth = 121
          ControlOptions.ShowBorder = False
          Index = 0
        end
        object dxLayoutItem5: TdxLayoutItem
          Parent = dxLayoutAutoCreatedGroup1
          AlignVert = avCenter
          CaptionOptions.Text = 'Scan'
          CaptionOptions.Visible = False
          Control = ScanButton
          ControlOptions.OriginalHeight = 21
          ControlOptions.OriginalWidth = 75
          ControlOptions.ShowBorder = False
          Index = 1
        end
        object dxLayoutAutoCreatedGroup1: TdxLayoutAutoCreatedGroup
          Parent = LayoutControlMainGroup_Root
          LayoutDirection = ldHorizontal
          Index = 0
          AutoCreated = True
        end
        object dxLayoutGroup1: TdxLayoutGroup
          Parent = LayoutControlMainGroup_Root
          CaptionOptions.Text = 'Log'
          ButtonOptions.Alignment = gbaLeft
          ButtonOptions.Buttons = <>
          ButtonOptions.ShowExpandButton = True
          Expanded = False
          UseIndent = False
          Index = 2
        end
      end
      object SQLGridPopupMenu: TcxGridPopupMenu
        Grid = SQLGrid
        PopupMenus = <>
        Left = 1048
        Top = 360
      end
      object SQLStyleRepository: TcxStyleRepository
        Left = 952
        Top = 320
        PixelsPerInch = 96
        object cxStyle1: TcxStyle
          AssignedValues = [svFont]
          Font.Charset = DEFAULT_CHARSET
          Font.Color = clWindowText
          Font.Height = -11
          Font.Name = 'Courier New'
          Font.Style = []
        end
      end
      object dxLayoutLookAndFeelList1: TdxLayoutLookAndFeelList
        Left = 856
        Top = 368
        object dxLayoutCxLookAndFeel1: TdxLayoutCxLookAndFeel
          LookAndFeel.NativeStyle = False
          LookAndFeel.ScrollbarMode = sbmClassic
          LookAndFeel.SkinName = 'Office2013White'
          PixelsPerInch = 96
        end
      end
    end

    HTH

     

    /D

    • Like 1

  4. OK. Just went in to check on that little tool. :classic_blush:

     

    Turns out i have used DevExpress and RTC 😞 DevExpress because i do not have to do anything but fill a grid and there's search, sorting, filtering, pinning and all else. The only function i added was a checkbox to show the full row-height for the statements or just one row.

    RTC is because i'm familiar with its JSON classes. The RTC JSON classes can be replaced with something else.

     

    I just want to make it clear that for a "I made this" sharing i'd have to at *least* 1) get rid of 3rd party 2) implement settings for paths, properties selection et.al. 3) consider using project files in stead of paths, 4) consider an exe or plugin for the IDE... the to-do list could grow exponentially.

     

    Another thing that i dearly have to apologise for is the mention of Delphi-AST, i have no idea what i was on about. I used this brilliant project:

     

    https://github.com/masonwheeler/DFMJSON

     

    not Delphi-AST at all. Apologies. Really. I should not post so fast. :classic_blush: :classic_blush:

     

    This is the complete non-visual unit, what properties i'm interested in are hard-coded (!):

     

    unit Data.ObjectCollector;
    
    interface
    
    uses
      System.SysUtils,
      System.Classes;
    
    type
      TStatementInfo = record
        FormName: string;
        StatementName: string;
        StatementClass: string;
        StoredProcName: string;
        StatementSQL: string;
      end;
    
      TObjectCollectoDataModule = class(TDataModule)
      private
        procedure DoCollect(
          const filename: string;
          const onFound: TProc<TStatementInfo>;
          const onSuccess, onErr: TProc<string>);
      public
        procedure RunCollect(
          const path, mask: string; recurse: boolean;
          const onFound: TProc<TStatementInfo>;
          const onSuccess, onErr: TProc<string>);
      end;
    
    var
      ObjectCollectoDataModule: TObjectCollectoDataModule;
    
    implementation
    
    uses
      System.Types,
      System.IOUtils,
      System.StrUtils,
      dwsJSON,
      DFMJSON,
      rtcInfo;
    
    {%CLASSGROUP 'Vcl.Controls.TControl'}
    
    {$R *.dfm}
    
    { TObjectCollectoDataModule }
    
    procedure TObjectCollectoDataModule.DoCollect(
      const filename: string;
      const onFound: TProc<TStatementInfo>;
      const onSuccess, onErr: TProc<string>);
    var
      I, J: Integer;
      dfm: TdwsJSONObject;
      rtcValue: TRtcValue;
      rtcArray: TRtcArray;
      lCurrentStatement: TStatementInfo;
    begin
      dfm := nil;
      try
        try
          try
            dfm := DFMJSON.Dfm2JSON(filename);
          except
            on EParserError do
            try
              dfm := DFMJSON.DfmBin2JSON(filename)
            except
              on E: Exception do
              begin
                if assigned(onErr) then
                  onErr(format('Error while parsing %s.  Exception %s: %s', [filename, e.ClassName, e.Message]));
                exit;
              end;
            end;
          end;
    
          rtcValue := TRtcValue.FromJSON(dfm.ToString);
          try
            if rtcValue.isType = rtc_Record then
            begin
              if Assigned( OnSuccess ) then
                OnSuccess(Format( 'Processed %s (%s)', [
                                  rtcValue.asRecord.asString['$Class'],
                                  rtcValue.asRecord.asString['$Name']]));
    
              lCurrentStatement.FormName := rtcValue.asRecord.asString['$Name'];
              if rtcValue.asRecord.isType['$Children'] = rtc_Array then
              begin
                rtcArray := rtcValue.asRecord.asArray['$Children'];
                for I := 0 to rtcArray.Count - 1 do
                  if rtcArray.isType[I] = rtc_Record then
                    if (rtcArray.asRecord[i].asString['$Class'] = 'TIB_Cursor') or
                       (rtcArray.asRecord[i].asString['$Class'] = 'TIB_DSQL') or
                       (rtcArray.asRecord[i].asString['$Class'] = 'TIB_Query') or
                       (rtcArray.asRecord[i].asString['$Class'] = 'TIB_StoredProc') then
                    begin
                      if Assigned( OnSuccess ) then
                        OnSuccess(Format('   Found %s (%s)', [
                                         rtcArray.asRecord[i].asString['$Name'],
                                         rtcArray.asRecord[i].asString['$Class']]));
    
                      if Assigned( OnFound ) then
                      begin
                        lCurrentStatement.StatementName   := rtcArray.asRecord[i].asString['$Name'];
                        lCurrentStatement.StatementClass  := rtcArray.asRecord[i].asString['$Class'];
                        lCurrentStatement.StatementSQL    := '';
                        if rtcArray.asRecord[i].asString['$Class'] = 'TIB_StoredProc' then
                          lCurrentStatement.StoredProcName := AnsiDequotedStr(rtcArray.asRecord[i].asText['StoredProcName'], '''') else
                          lCurrentStatement.StoredProcName :=  '';
                        if rtcArray.asRecord[i].isType['SQL.Strings'] = rtc_Array then
                          for J := 0 to rtcArray.asRecord[i].asArray['SQL.Strings'].Count - 1 do
                          begin
                            lCurrentStatement.StatementSQL :=
                              lCurrentStatement.StatementSQL +
                              AnsiDequotedStr(rtcArray.asRecord[i].asArray['SQL.Strings'].asString[J], '''') + #13#10;
                          end;
                        OnFound(lCurrentStatement);
                      end;
                    end;
              end;
            end;
          finally
            rtcValue.Free;
          end;
    
        except
          on E: Exception do
            if assigned(onErr) then
              onErr(format('Error while converting %s.  Exception %s: %s', [filename, e.ClassName, e.Message]));
        end;
      finally
        dfm.Free;
      end;
    end;
    
    procedure TObjectCollectoDataModule.RunCollect(
      const path, mask: string; recurse: boolean;
      const onFound: TProc<TStatementInfo>;
      const onSuccess, onErr: TProc<string>);
    var
      files: TStringDynArray;
      filename: string;
      option: TSearchOption;
    begin
      if recurse then
        option := TSearchOption.soAllDirectories else
        option := TSearchOption.soTopDirectoryOnly;
      files := TDirectory.GetFiles(path, mask, option);
      for filename in files do
        DoCollect(filename, onFound, onSuccess, onErr);
    end;
    
    end.

    Call RunCollect and get each component and property/ies back in the onFound procedure. The onSuccess and onErr is for the log.

    The rtcXXX functions is used to parse and walk the JSON hierarchy. It's very similar to reading and processing XML. Just ask me what happens if it's unclear.

    As you can see the real work is done by the DFMJSON project in the Dfm2JSON and dfm.toString functions.

     

    Here are two screenshots:

    image.thumb.png.cee178e6d95b888c3382dd69c4368e2a.png

     

    ...and...

     

    image.thumb.png.88eb346eac95dcd75928d09f45114bae.png

     

    but that is very need-specific. I.e. what do you want to do with it all.

     

    HTH and Regards,

     

    /Dany


  5. 55 minutes ago, David Schwartz said:

    They're scattered across a few hundred source files. It's probably worth taking a look. Do you want to post it here and I can grab it, then you can leave it or delete it later?

    I'll think of sumthing during work hours tomorrow.

    • Like 1

  6. I built my 'SQL-DFM' browser using DX. If you have DX i can send the sources. The AST part i OS. But it hardly matters, look at AST demo, 700 strings takes less than a, sec to scan. Then you can even output or rearrange the props in the DFM. Or as i did, collect all in a neat grid with search, filters, grouping, sorting... you essentially write you own "navigator" for specific properties.


  7. @Sherlock - the modern code-editors have an *extensive* "API" that asks some process *lot's* of things. Here's the intro from VC:

     

    https://code.visualstudio.com/docs/languages/overview#_language-features-in-vs-code

     

    So writing a language-server is not a trivial task. It also requires you to do some background comping.

     

    I assume that "Language Server" without specifying Visual Code or Atom or any other capable editor won't do. If you want to support multiple editors you'll need to cater for dissimilarities (i suppose). 

     

    HTH,

     

    /Dany


  8. I have longed for this for ages!! For example, DX has a "BarManager" and that component only have on (1) ImageList property. Lots of icons, one small mistake, boom. Adding to the complexity when we have actually different icons for "small" and "large".

     

    However, with this solution, it is mandated that all components having an "ImageIndex" property needs to be of a certain class. So if i have prerequisites in a project to (for example) only use DX "Editors" then this is not a solution i can use. Am i correct?

     

    TIA,

     

    /Dany

×