I have an alpha-quality RealStudio project that does this. I stopped working on it because I can’t think of a use for it that wouldn’t violate the Xojo EULA. Here it is examining its own .rbvcp file:
At the root of the class hierarchy is the BaseTag
class, representing a single Xojo text format #tag
entry. The project file class is a subclass, as are top-level siblings like ClassTag
and MethodTag
. Class-like project items inherit from the ClassTag
class; method-like project items inherit from the MethodTag
class. etc.
BaseTag
|-ProjectFile
|-MethodTag
| +-EventTag
| +-DelegateTag
| -ClassTag
| +-WindowTag
| +-ControlTag
etc.
The BaseTag
class has computed properties that call protected methods of the BaseTag
class which are then overridden by subclasses as necessary.
So, for example, the BaseTag
class has a property called Signature As String
, which calls Tag.GetSignature() As String
, which is overridden by the ClassTag
, MethodTag
, etc. subclasses to return an appropriately-formatted signature (Protected Class Foo
, Private Sub Bar(i As Integer)
, etc.)
Each subclass knows how to parse its particular type of project item. The ProjectFile class knows about file-level items like classes, modules, build automation, etc. that are listed in the project manifest. For each of these it creates an appropriate subclass of BaseTag
, which then takes over parsing and which may or may not itself create subclasses of BaseTag
for its own sub-items.
So, ProjectFile.ParseNow()
encounters a class file, and calls ClassTag.Constructor
to parse the whole file. ClassTag.Constructor
encounters methods and properties of the class and calls MethodTag.Constructor
and PropertyTag.Constructor
to parse those items and store them as a property of the ClassTag
.
Once parsed, you can do interesting things, almost like Introspection but with the source code (extrospection?):
Dim prj As New RBParse.ProjectFile(TheProjectAsFolderItem)
prj.ParseNow()
Dim tagtypes() As Integer = Array(TAG_TYPE_PROPERTY, TAG_TYPE_COMPUTED)
Dim props() As RBParse.Tag = prj.GetTagsByType(tagtypes)
For i As Integer = 0 To UBound(props)
If props(i).Scope = "Protected" Then ' .Scope inherited from BaseTag
' etc.
Methods like GetTagsByType
, GetTagsByName
, and GetTagsByContents
, and properties like Scope As String
and RichSignature As String
are inherited from BaseTag
and can be called on any subclass.
IDK if that’s the best way to do it, but it does work. The code is not public because of the previously-mentioned EULA concerns, but if anyone’s interested in looking at it I can add them to the private Github repo. I’ve also uploaded a Windows build in case anyone wants to play with it. No EULA concerns since it’s read-only.