Project model

This is sort of “Xojo related” since its for a project I’m working on - in C# - that can read / edit / save Xojo projects (probably only write text projects but read anything )

So since most of what the Xojo IDE manipulates is data about project items, and not actual instances of classes/modules/windows/etc I’m thinking about how to represent all this data in a meaningful way

Obviously I’ll need a data structure to represent a “Project”
Then I’ll need “ProjectItems”

and now the question I need / want feedback about
Should I subclass ProjectItem and make a “ProjectClass” class, a “ProjectModule” class, “ProjectWindow” class, etc ?
Maybe I have a property on Project item that is an enumerated type that indicates the base type ? (Class, Module,Window, Application, etc?)
And based on that enumeration then I can determine whether methods can be added, events, properties, etc ?

Thoughts ?

I would think if you do this, ProjectItem would be verrrry empty and wouldn’t serve much purpose. Can you illustrate a reason / use case where ProjectItem would have a common property for all? Maybe perhaps a Save method I guess? I understand the phrasing flow that creates this desire, but in a practical sense I’m not sure I am finding a reason to.

Since I’m not favoring a purpose for ProjectItem I don’t think I can weigh in on your other two questions. (This is in Xojo terms:) Maybe as an Interface it would allow you to store all project items as an array property of Project, but other than organization it doesn’t seem to serve a highly useful superclass purpose.

Just my thoughts. I could be sold on this either way, honestly.

Interface to decide what can have method and what cannot might be better than inheriting. As with inheriting you will fast find your self boxed in I would think.

So could be IMethodHolder, IPropertyHolder, IEnumHolder, etc. And when you ask the node if you can add method to it then you just check if it is IMethodHolder

ProjectItem at the very least has 2 properties - Name and perhaps an ID

What I’m toying with is avoiding a hierarchy like - the Prefix is just because there are MY classes to hold data about items in a project NOT Xojo things (like folderitems)

CProjectitem
     CModuleItem
          CClassItem
     CWindowItem
     CFolder
     CMenuBar
     CContainer

etc because really there might not be that much utility

just thinking out loud here

However, I can see that IF I do not have some subclasses then code to read / write a CProjectItem out properly would be full of select case statements - usually a sign you need subclasses

hmmmmm

Yeah an interface makes a pile of sense but if I dont have any level of subclasses then I run into the same issue since I cant dynamically create instances that implement those interfaces …

hmmmmmm …

I don’t know but with Java you could create dynamical this interfaces. I am not deep enough into C# / Dotnet but as far as I know you have no chance there for dynamical code injection. That is one thing you could do with Java. Could possibly help you for this project.

I would always subclass that items. For the enumerated Type I would do an interface. With dependency injection you can then use the interface after detecting and you’ll have the needed type. With dependency injection you would be able to do that Job. I wrote two VM’s for Web and Java-Xcode which do exactly that. It is functional no problem to do it. Only time will be needed to realize it.

Something like a little own VM which does that Job. After you would have always a clean structure you can even use to transpire that codes to another Language. That it is working is proven by many, for example CodenameOne - Java CN1UI to Android (Android VM), Java CN1UI to IOS (Parpar VM) and B4I (JavaFX to to IOS with Parpar VM similar Type) and JavaFX to Android with Android VM. With this systematical approach you can do that Jobs.

That is not only possible in Java, it is also possible in other languages and here only an example.

I hadn’t thought about those. In that case, I think a class (and the hierarchy you are trying to avoid) would be beneficial.

This is not something I have heard before. From the serializable class approaches I’ve seen, they’ve used select case to read / write / in / out. I had assumed that was how it was done.

I’m not using Java hence why the question focused on C#

Sorry Tim, answer is for @npalardy

While Dependency injection and reflection are the ways how I can do that with Java. So you could look how to do that in C#. that’s it. I can only speak about that how I was doing that kind of Jobs successful. Nothing else. And while I was doing exactly that Jobs successful and I know how to I can tell you exactly about that. and I am in the hope that you will find a way to do all of this also in C# with nearly the same approaches but a few changes. That’s why. To tell you how to get it on. While I was not programming that in C#. And I know that you want to use C#. Therefore you can use it or leave it. But it was not to tell you: use Java. It was to say: look hoe it can be done in java and transfer that to C# but I have no Idea in Detail to do in C#. I wanted to help and nothing else.

I’ve never done it but it’s possible and doesn’t look terribly difficult offhand to inject generated code into C# methods at runtime … IIRC it’s in the Roslyn namespace. Not saying that’s the best solution, it’s just a possibility to consider. Honestly I haven’t had time to read this thread in detail and think about it much. And it wouldn’t be my first choice.

I’ve done things like have quasi-abstract (or actual abstract) methods that do some default action (or nothing at all) but provide common implementations that can be called from an inheriting class. Something like:

protected virtual void MyHook() {
  MyDefaultHookBehavior();
}

protected void MyDefaultHookBehavior() {
  ...
}

protected void MyAlternativeHookBehavior() {
 ...
}

Then in the inheriting class:

protected override void MyHook() {
  MyAlternativeHookBehavior(); // or a whole other implementation, whatever
}

Of course all the standard dependency injection techniques can be deployed as well.

I guess in the end the questions is more

IF you were origin an IDE to read Xojo projects how would YOU represent the ditems IN the project itself ?

Obviously there are things common to EVERY kind of Xojo project
Classes, Modules, Folders, Interfaces etc
its all just data about these kinds of things

I had been thinking that I should have a hierarchy like

  CProjectItem 
     |
     +- CModule 
     |     |
     |     + CClass
     |         |
     |         + CInterface
     | 
     +- CFolder
     |
     +- CWindow
     |
     +- CMenuBar
    ... etc ...

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.

1 Like

I can’t hold a candle to you or charronn0, having only done one Xojo project and probably don’t have that great a grasp on best practices – in particular I’m not familiar with how modules are related to classes. But for example if you define an interface, that’s a project item which is one of zero or more interfaces a class might implement. So it’s first in my mind a composition matter rather than in inheritance one. Modules, class, and interfaces are all bits of code which are then composed with each other in various ways.

So all three of those project items could be a CCode class with a type flag or there could be a CCode abstract base class that CModule, CClass and CInterface inherit from or an ICode interface that CCode, CModule and CClass implement … but you would also need runtime collections of those instances to show how they are used. A class instance would have a collection of interfaces to represent what interfaces the class implements.

After all, a single interface could be potentially implemented by any number of classes.

Apologies if I’m missing the point.

trust me you’re not wrong

Im just trying to structure the DATA that represents classes modules etc etc etc

So in my diagram a model and a class are VERY similar
The major differences

  1. a module cant be used as the superclass for anything
  2. a class cannot contain other classes

And the data about a class interface is very much like a class except

  1. in Xojo it cannot define properties events etc - just methods
  2. the methods it does define cant have code

I might and I CAN avoid EULA concerns since I’m NOT writing this in Xojo :stuck_out_tongue:
Anyone interested I can add to my private GitHub repo as well :slight_smile:

My goal is to deal with the things that drive me nuts IN the current IDE

Like pasting code in and hitting CMD+R fast and it obviously compiling the code I just replaced by pasting … the old code gets compiled & when the source is edited again the OLD source I replied is back (ARGHHH !!!)

And the timers for reformatting etc that leave everything out of sync and the editor in a state I just feel its unreliable

I’d like to be part of that, Norm. My spare time is not copious at the moment but I DO have to maintain that one Xojo project for use in my gig and the IDE is slow and flaky.