Menu ▾ ▴

#488 Class Browser do not show a class

Closed
closed-fixed
None
5
2026-05-12
2026-05-06
markbd13
No

Description:
Class browser does not show classes when short class declaration is used

type

  TControlM = class(TControl);
  TCustomGroupBoxM = class(TCustomGroupBox);
  TFrameBaseDS = class(TFrameBase)
  end;

Class browser tree:
(...)
TFrameBase
-- TControlM.TCustomGroupBoxM.TFrameBaseDS

there is no expected element
TFrameBase
-- TFrameBaseDS

Bug Details:
The bug is reproducible 100% of the time

Steps:

  1. Define a unit as in the description
  2. Open Class Browser
  3. Refresh data (F5)

Discussion

  • markbd13

    markbd13 - 2026-05-08

    (by CLAUDE.AI, Sonnet 4.6):

    Bug fix: Class Browser incorrectly nests classes that follow short class declarations

    Problem

    When a Pascal unit contains "short" (empty-body) class declarations immediately before a full class declaration, the Class Browser displays the full class with a concatenated name instead of showing it as a standalone entry.

    Example source:

    type
      TControlM = class(TControl);
      TCustomGroupBoxM = class(TCustomGroupBox);
      TFrameBaseDS = class(TFrameBase, ISetGBWhereWidth, ...)
        DataSource: TDataSource;
        ...
      end;
    

    Expected tree:

    TFrameBase
    -- TFrameBaseDS

    Actual (buggy) tree:

    TFrameBase
    -- TControlM.TCustomGroupBoxM.TFrameBaseDS
    Root cause

    FindClassEndIndex in GX_ClassMgr.pas is used by DetectNesting to locate the closing end token for each class declaration. It scans forward from the class identifier and tracks nesting depth by counting class/end pairs.

    When called for TControlM = class(TControl);, it encountered class( and incremented the depth counter, expecting a matching end. But short class declarations have no body and no end, so the depth counter was never decremented back to zero. The function continued scanning into subsequent declarations, eventually finding the end of TFrameBaseDS and returning it as the "end" of TControlM.

    As a result, DetectNesting pushed TControlM onto the nesting stack, then TCustomGroupBoxM (similarly affected), and finally nested TFrameBaseDS inside both of them — producing the TControlM.TCustomGroupBoxM.TFrameBaseDS name.

    Fix

    Two changes were made to FindClassEndIndex in Source/Framework/GX_ClassMgr.pas:

    Early exit at function entry. Before the main scanning loop, the function now checks whether the class identified by IdentIndex is itself a short declaration. It scans forward to the class keyword, skips the optional ancestor list in parentheses, and checks if the next token is ;. If so, the function returns -1 immediately, correctly indicating that there is no matching end for this class.

    Short class detection in the main scan loop. When the main loop encounters a class keyword followed by (, it now skips to the matching ) and checks whether the next token is ;. If so, it treats this as a short class declaration (no body) and does not increment the depth counter. This handles the case of short class declarations appearing as nested types inside a full class body.

     
  • Thomas Mueller

    Thomas Mueller - 2026-05-10
    • status: open --> closed-fixed
    • assigned_to: Thomas Mueller
    • Group: New --> Closed
     
  • Thomas Mueller

    Thomas Mueller - 2026-05-10

    Thanks for the patch. I have applied it in a modified form in revision #5383
    please retest.

     
  • markbd13

    markbd13 - 2026-05-12

    Retested.
    Works as expected.👍

     

Log in to post a comment.