Generate includes for types referenced in body of inferred methods [message #1386150] |
Fri, 13 June 2014 12:08  |
Eclipse User |
|
|
|
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 #1386154 is a reply to message #1386153] |
Fri, 13 June 2014 13:26   |
Eclipse User |
|
|
|
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 #1728105 is a reply to message #1728102] |
Thu, 31 March 2016 03:17   |
Eclipse User |
|
|
|
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!
|
|
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.05237 seconds