Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » JVM Inferrer -- Possible to generate two declared types that reference each other?
JVM Inferrer -- Possible to generate two declared types that reference each other? [message #1834249] Thu, 05 November 2020 19:00 Go to next message
Ben Holland is currently offline Ben HollandFriend
Messages: 34
Registered: April 2019
Member
I need to generate a type with a JVM Inferrer that references another generated type. Apologies in advance for the somewhat contrived example.
Entity E1 has E2,E3 {
  field E2 e2;
  field E3 e3;
  operation void foo() {
    e2.bar();
  }
}

Entity E2 {
  field E1 parent;
  operation void bar() {
    parent.e3.baz();
  }
}

Entity E3 {
  field E1 parent;
  operation void baz() {
    System.out.println("test");
  }
}


The corresponding Java code would be something like:

public class E1 {
  public E2 e2;
  public E3 e3;
 
  pubic E1(){ initialize(); }

  private void initialize(){
   this.e2 = new E2(this);
   this.e3 = new E3(this);
  }

  public void foo(){
    e2.bar();
  }
}

public class E2 {
  public E1 parent;
  public E2(E1 parent){
    this.parent = parent;
  }
  public void bar(){
    parent.e3.baz();
  }
}

public class E3 {
  public E1 parent;
  public E3(E1 parent){
    this.parent = parent;
  }
  public void baz(){
    System.out.println("test");
  }
}


Is this possible? It seems that no matter which order I generate the types (top down or bottom up) I run into issues. It's like a type is a snapshot of an earlier incomplete definition of the referenced type. When I add an XExpression for the operation the "parent" reference resolves fine, but the "e3" reference from parent stops compilation because e3 is missing. However if I comment the expression the classes generate and then the field is present and I can add the expression back and it will compile (although a full clean/build does not succeed).

The JVM Language tutorial sort of hints at this with "Every JvmDeclaredType you create in the model inference needs to be passed to the acceptor in order to get recognized. ... It is important to understand that the creation and assignment of a qualified name is done in an early phase where the compiler collects all global symbols. You cannot resolve type references at this point."
Re: JVM Inferrer -- Possible to generate two declared types that reference each other? [message #1834250 is a reply to message #1834249] Thu, 05 November 2020 19:11 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
simply using "full.qualiefied.name".typeRef does not work?
also: if all references are in the model?
where is the problem

=> can you please be more concrete


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de

[Updated on: Thu, 05 November 2020 19:25]

Report message to a moderator

Re: JVM Inferrer -- Possible to generate two declared types that reference each other? [message #1834253 is a reply to message #1834250] Thu, 05 November 2020 20:28 Go to previous messageGo to next message
Ben Holland is currently offline Ben HollandFriend
Messages: 34
Registered: April 2019
Member
Ah ok maybe this is my problem. I wasn't using the QualifiedName rule. I just generate my own "x.y.z" string for the types as a string I fed to typeRef(). Do I have to use the QualifiedName element to do this?
Re: JVM Inferrer -- Possible to generate two declared types that reference each other? [message #1834254 is a reply to message #1834253] Thu, 05 November 2020 21:16 Go to previous messageGo to next message
Ben Holland is currently offline Ben HollandFriend
Messages: 34
Registered: April 2019
Member
I'm actually somewhat confused now. I see that I can inject the IQualifiedNameProvider instance like in the JVM Language example, but it looks like the toClass method just calls toString on the QualifiedName. So if I create my own string own string or use the QualifiedName provider the result should be the same right?

public JvmGenericType toClass(/* @Nullable */ EObject sourceElement, /* @Nullable */ QualifiedName name, /* @Nullable */ Procedure1<? super JvmGenericType> initializer) {
		return toClass(sourceElement, name != null ? name.toString() : null, initializer);
	}
	
	public JvmGenericType toClass(/* @Nullable */ EObject sourceElement, /* @Nullable */ String name, /* @Nullable */ Procedure1<? super JvmGenericType> initializer) {
		final JvmGenericType result = createJvmGenericType(sourceElement, name);
		if (result == null)
			return null;
		associate(sourceElement, result);
		return initializeSafely(result, initializer);
	}

Re: JVM Inferrer -- Possible to generate two declared types that reference each other? [message #1834255 is a reply to message #1834254] Thu, 05 November 2020 21:31 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
Yes. Can you please provide a reproducing example

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: JVM Inferrer -- Possible to generate two declared types that reference each other? [message #1834261 is a reply to message #1834255] Fri, 06 November 2020 06:10 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

Behind Xtext you have an EMF model and EMF Java generation does not support anything other than default no-argument constructors. Fields in auto-generated code can only be set by the relevant setXXX() method. The need for this limitation is fairly obvious once you consider the problem of loading from XMI where you want to start with an EObject for the parent element and elaborate as the child elements are discovered without being very clever about recognising a subset of elements to align to construction parameters and a possibly insoluble nightmare of dependencies between construction argument tuples. When coding manually with EMF, you can have constructors with arguments, which can sometimes be helpful but often proves to be a mistake since you throw away save/load and other things go wrong. A reversion to normal often proves necessary.

You can however have objects referencing each other by using bidirectional references in manually defined Ecore. I doubt this is possible using Xtext's auto-generation that I never use since it is unable to support many of Ecore's capabilities. Use a manually defined Ecore. Xtext is very good for T2M grammars, it is poor for metamodeling.

Regards

Ed Willink



Re: JVM Inferrer -- Possible to generate two declared types that reference each other? [message #1834827 is a reply to message #1834261] Wed, 18 November 2020 16:29 Go to previous message
Ben Holland is currently offline Ben HollandFriend
Messages: 34
Registered: April 2019
Member
Thank you all. I just wanted to follow up with what I observed. I worked to simplify my issue I was seeing to the representative example that I showed above. When I went to create a concrete version of the example I used the QualifiedNameProvider (instead of resolving my own type strings) and everything worked. I spent a long time poking around in the XText code around resource sets and noticed that after a type reference was resolved it would fail to find the the type reference and instead would create a new type and then everything would fall apart from there. One thing I did realize was that originally I was not being very careful about what EObject I was mapping to a JVM type and because I was manually resolving crossreferences in the grammar I got a situation where two different EObject instances mapped to one type. Anyway reworking my DSL with QualifiedNameProvider and XText CrossReferences and being careful about each EObject I map to a JVM type fixed my issue.
Previous Topic:Disabling inter-file Cross referencing
Next Topic:64bit figure
Goto Forum:
  


Current Time: Tue Apr 23 11:30:10 GMT 2024

Powered by FUDForum. Page generated in 0.03362 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top