Skip to main content



      Home
Home » Modeling » TMF (Xtext) » Generate includes for types referenced in body of inferred methods
Generate includes for types referenced in body of inferred methods [message #1386150] Fri, 13 June 2014 12:08 Go to next message
Eclipse UserFriend
I have an XBased grammar that uses a JvmModelInferrer to generate .java files for the model elements. If the body of a method for an inferred type refers to a JVM type that isn't a field or method parameter of the class, I have to include the fully qualified name of the type. Is there any way to have these types added to the generated import statements of the generated .java file?

I have added the following method generation to the Domainmodel example to demonstrate. The method builds a List<String> of all the features in the entity and then converts the List to a String[] as the return. Both java.util.List<String> and java.util.ArrayList<String> have to be fully qualified in the generation text. These are the types I'm trying to get import statements generated for.

members += entity.toMethod("getFeatures", entity.newTypeRef(String).addArrayTypeDimension) [
	body = [append('''
		java.util.List<String> featureNames = new java.util.ArrayList<String>();
		«FOR f:entity.features»
			featureNames.add("«f.name»");
		«ENDFOR»
		return featureNames.toArray(new String[featureNames.size()]);
	''')]


The code generates a method similar to:
  public String[] getFeatures() {
    java.util.List<String> featureNames = new java.util.ArrayList<String>();
    featureNames.add("Name");
    featureNames.add("age");
    return featureNames.toArray(new String[featureNames.size()]);
    
  }


I'm trying to get something like

import java.util.List;
import java.util.ArrayList;
...
  public String[] getFeatures() {
    List<String> featureNames = new ArrayList<String>();
    featureNames.add("Name");
    featureNames.add("age");
    return featureNames.toArray(new String[featureNames.size()]);
    
  }
Re: Generate includes for types referenced in body of inferred methods [message #1386153 is a reply to message #1386150] Fri, 13 June 2014 13:15 Go to previous messageGo to next message
Eclipse UserFriend
Hmmm it looks like all api for that is hidden. can you please file a enhancement request for better api (e.g. one that gives access to importmanager

as a workaround:

		body = [
		append(entity.newTypeRef(List, entity.newTypeRef(String)).type)
		append('''
		  featureNames = new ''')
		 append(entity.newTypeRef(ArrayList, entity.newTypeRef(String)).type)
		 .append('''();
		«FOR f:entity.features»
			featureNames.add("«f.name»");
		«ENDFOR»
		return featureNames.toArray(new String[featureNames.size()]);
	''')]]	
Re: Generate includes for types referenced in body of inferred methods [message #1386154 is a reply to message #1386153] Fri, 13 June 2014 13:26 Go to previous messageGo to next message
Eclipse UserFriend
hmmm actually it is not working but this is
package org.eclipse.xtext.example.domainmodel.jvmmodel

import com.google.inject.Inject
import java.util.ArrayList
import java.util.List
import org.eclipse.xtext.common.types.JvmField
import org.eclipse.xtext.example.domainmodel.domainmodel.Entity
import org.eclipse.xtext.example.domainmodel.domainmodel.Operation
import org.eclipse.xtext.example.domainmodel.domainmodel.Property
import org.eclipse.xtext.naming.IQualifiedNameProvider
import org.eclipse.xtext.xbase.jvmmodel.AbstractModelInferrer
import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor
import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1
import org.eclipse.xtext.xbase.typesystem.legacy.StandardTypeReferenceOwner
import org.eclipse.xtext.xbase.typesystem.references.OwnedConverter
import org.eclipse.xtext.xbase.typesystem.util.CommonTypeComputationServices

class DomainmodelJvmModelInferrer extends AbstractModelInferrer {
	
	@Inject extension JvmTypesBuilder
	@Inject extension IQualifiedNameProvider

@Inject
	private CommonTypeComputationServices services;

	def dispatch infer(Entity entity, IJvmDeclaredTypeAcceptor acceptor, boolean prelinkingPhase) {
		acceptor.accept(
			entity.toClass( entity.fullyQualifiedName )
		).initializeLater [
			
			members += entity.toMethod("getFeatures", entity.newTypeRef(String).addArrayTypeDimension) [
				
				val that = it
				
		body = [
			val StandardTypeReferenceOwner owner = new StandardTypeReferenceOwner(services, that);
		val OwnedConverter converter = new OwnedConverter(owner);
		var t1 = converter.toLightweightReference(entity.newTypeRef(List, entity.newTypeRef(String)))
		var t2 = converter.toLightweightReference(entity.newTypeRef(ArrayList, entity.newTypeRef(String)))
			
		
			
		append(t1)
		append(''' featureNames = new ''')
		 append(t2)
		 .append('''();
		«FOR f:entity.features»
			featureNames.add("«f.name»");
		«ENDFOR»
		return featureNames.toArray(new String[featureNames.size()]);
	''')]]
			
			
			
			documentation = entity.documentation
			if (entity.superType != null)
				superTypes += entity.superType.cloneWithProxies
			val procedure = entity.newTypeRef(Procedure1, it.newTypeRef())
			members += entity.toConstructor() []
			members += entity.toConstructor() [
				parameters += entity.toParameter("initializer", procedure)
				body = '''initializer.apply(this);'''
			]
			val fields = <JvmField>newArrayList()
			for ( f : entity.features ) {
				switch f {
			
					Property : {
						val field = f.toField(f.name, f.type)
						fields += field
						members += field
						members += f.toGetter(f.name, f.type)
						members += f.toSetter(f.name, f.type)
					}
			
					Operation : {
						members += f.toMethod(f.name, f.type ?: inferredType) [
							documentation = f.documentation
							for (p : f.params) {
								parameters += p.toParameter(p.name, p.parameterType)
							}
							body = f.body
						]
					}
				}
			}
			members += entity.toToStringMethod(it)
		]
	}
	
}
Re: Generate includes for types referenced in body of inferred methods [message #1386158 is a reply to message #1386154] Fri, 13 June 2014 14:44 Go to previous messageGo to next message
Eclipse UserFriend
Here is the bugzilla link for the feature request:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=437413

I'll look into the suggested work around.
Re: Generate includes for types referenced in body of inferred methods [message #1386216 is a reply to message #1386153] Sun, 15 June 2014 04:53 Go to previous messageGo to next message
Eclipse UserFriend
On 13/06/2014 19:15, Christian Dietrich wrote:
> Hmmm it looks like all api for that is hidden. can you please file a
> enhancement request for better api (e.g. one that gives access to
> importmanager
>
> as a workaround:
>
>
> body = [
> append(entity.newTypeRef(List, entity.newTypeRef(String)).type)
> append('''
> featureNames = new ''')
> append(entity.newTypeRef(ArrayList,
> entity.newTypeRef(String)).type)
> .append('''();
> «FOR f:entity.features»
> featureNames.add("«f.name»");
> «ENDFOR»
> return featureNames.toArray(new String[featureNames.size()]);
> ''')]]
>

If I remember correctly in Xtext 2.5.0 StringConcatenationClient has
been introduced to solve this issue.

In the inferrer you don't need to use it directly: you just use it for
the body, but you need to pass a multiline string directly (not using a
lambda); this should work (but I haven't tested it):

body = '''
«List<String>» featureNames = new «ArrayList<String>»();
'''

cheers
Lorenzo

--
Lorenzo Bettini, PhD in Computer Science, DI, Univ. Torino
HOME: http://www.lorenzobettini.it
Xtext Book:
http://www.packtpub.com/implementing-domain-specific-languages-with-xtext-and-xtend/book
Re: Generate includes for types referenced in body of inferred methods [message #1386218 is a reply to message #1386216] Sun, 15 June 2014 06:33 Go to previous messageGo to next message
Eclipse UserFriend
Hi,

it actually works but you have to care about generics yourself

'''
«List»<«String»> featureNames = new «ArrayList»<«String»>();
'''
Re: Generate includes for types referenced in body of inferred methods [message #1728101 is a reply to message #1386218] Thu, 31 March 2016 02:43 Go to previous messageGo to next message
Eclipse UserFriend
I am trying to solve a similar problem and came across this old thread.

Is there now a more general solution to this?

For example, I am building the body of a complicated method, and find it easier to rely on a StringBuilder than a multiline String.

So, in the end, my method creation looks like:

source.toMethod(methodName, typeRef(boolean)) [
   body =
'''
«methodBodyBuilder.toString»
return false;
''']


Depending on the control, a certain type may or may not be referenced to the String Builder. However, this is not triggering the auto-import of the type.

Is there any way to explicitly pass a type to the import manager so that the type will be imported in this case?
Re: Generate includes for types referenced in body of inferred methods [message #1728102 is a reply to message #1728101] Thu, 31 March 2016 02:47 Go to previous messageGo to next message
Eclipse UserFriend
Make the Method builder of Type StringConcatenationClient and leave oft the toString


def StringConcatenationClient methodBuilder(....) {
'''...'''
}
Re: Generate includes for types referenced in body of inferred methods [message #1728105 is a reply to message #1728102] Thu, 31 March 2016 03:17 Go to previous messageGo to next message
Eclipse UserFriend
Hmm, I'm not sure if I fully understand.

Are you saying I should use a StringConcatenationClient instead of using a StringBuilder for appending the bits of my method body?

I tried subclassing StringConcatenationClient to do this, but it does not offer the same interface as StringBuilder. There is an appendTo method, but it's not clear how to set things up to work properly.

Just to clarify, my current pattern is:


val StringBuilder methodBodyBuilder = new StringBuilder

// iterate through EObjects, appending Strings to the methodBodyBuilder
// e.g. which I would want to import "Type"
methodBodyBuilder.append('''«Type».method(«args»)'''

// Once this is all done, build the method, using the StringBuilder:

source.toMethod(methodName, typeRef(boolean)) [
   body =
'''
«methodBodyBuilder.toString»
return false;
''']


I also tried just dumping my StringBuilder's contents into a StringConcatenationClient, but that did not cause the type to be imported either.

Thanks yet again!

Re: Generate includes for types referenced in body of inferred methods [message #1728106 is a reply to message #1728105] Thu, 31 March 2016 03:23 Go to previous messageGo to next message
Eclipse UserFriend
as i said. forget the damn string builder.
Re: Generate includes for types referenced in body of inferred methods [message #1728109 is a reply to message #1728106] Thu, 31 March 2016 03:46 Go to previous messageGo to next message
Eclipse UserFriend
Ok, fair enough.

So, is there a usage example for a StringConcatenationClient which is appended to incrementally in this way, to build up a method over time, without relying on one single multiline template?
Re: Generate includes for types referenced in body of inferred methods [message #1728110 is a reply to message #1728109] Thu, 31 March 2016 03:51 Go to previous messageGo to next message
Eclipse UserFriend
StringConcatenationClient _client = new StringConcatenationClient() {
@Override
protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
_builder.append("binder.bind(");
_builder.append(IResourceDescriptions.class, "");
_builder.append(".class).to(");
_builder.append(ResourceSetBasedResourceDescriptions.class, "");
_builder.append(".class);");
}
};
Re: Generate includes for types referenced in body of inferred methods [message #1728112 is a reply to message #1728110] Thu, 31 March 2016 03:52 Go to previous message
Eclipse UserFriend
btw i dont get the over time argument

''''
<<firstSubMethod>>
<<secondSubMethid>>
<<IF ...>>
<<ENDIF>>
....
''
Previous Topic:RPG, RPGLE and RPG Free Format
Next Topic:XMIException when binding two languages
Goto Forum:
  


Current Time: Wed Jul 23 13:42:30 EDT 2025

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

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

Back to the top