Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Customize IQualifiedNameProvider Problem(Customized qualifiedNames don't appear (cusctomized) in Scope)
Customize IQualifiedNameProvider Problem [message #1514718] Wed, 17 December 2014 14:44 Go to next message
Alexander R is currently offline Alexander RFriend
Messages: 211
Registered: July 2013
Senior Member
Hi,

I customized my IQualifiedNameProvider to define a special QualifiedName for operatations in my dsl. This works well and I can see the result by grabing some
IEObjectDescription from a model in a testcase. Via:

ResourceDescriptionsProvider.getResourceDescriptions(eObject).getExportedObjects()


But when I calculate a scope for a special context ( operation-call-reference) and here check the IEObjectDescription->QualifiedName inside the Scope, the QualifiedNames are not changed! They are still simple names of the operations.

The important part of the grammar looks like this:
Operation:
name=ID '('...params..')' ;

OpCall:
reference = [Operation]


Does the customization do not work, because of the "name=ID"-Pattern in the Grammar? Or am I doing something else wrong?
Btw. The own IQualifiedNameProvider is registered in the module..

Thanks for your help,
Alex
Re: Customize IQualifiedNameProvider Problem [message #1514806 is a reply to message #1514718] Wed, 17 December 2014 16:23 Go to previous messageGo to next message
Uli Merkel is currently offline Uli MerkelFriend
Messages: 250
Registered: June 2013
Senior Member
AFAIK, defining the reference as you have done uses the default which is the name for the reference.
The example in the documentation used for qualified names (https://www.eclipse.org/Xtext/documentation.html#_4)

reference = [Operation|QualifiedName]
QualifiedName: ID ('.' ID)* ;
Re: Customize IQualifiedNameProvider Problem [message #1514843 is a reply to message #1514806] Wed, 17 December 2014 16:57 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
how does your qualifiedName look like?

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize IQualifiedNameProvider Problem [message #1514884 is a reply to message #1514843] Wed, 17 December 2014 17:42 Go to previous messageGo to next message
Alexander R is currently offline Alexander RFriend
Messages: 211
Registered: July 2013
Senior Member
Hi,

for the following example:

class B{}
class A {
a:String; 			
myOp(age: B, name:String){
this.a;
}}


All the QualifiedNames looks like this:

B,
 A, 
 A.a, 
 A.myOp(age[0..1],String[0..1]):void, 
 A.myOp(age[0..1],String[0..1]):void.age, 
 A.myOp(age[0..1],String[0..1]):void.name


For an operation I just create a operation signature. ( for referenced types of parameters I just use the paramterame)

~Alex

[Updated on: Wed, 17 December 2014 17:46]

Report message to a moderator

Re: Customize IQualifiedNameProvider Problem [message #1514921 is a reply to message #1514884] Wed, 17 December 2014 18:20 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
and how should the reference look like? the very same?
A.myOp(age[0..1],String[0..1]):void.name?


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize IQualifiedNameProvider Problem [message #1514931 is a reply to message #1514921] Wed, 17 December 2014 18:33 Go to previous messageGo to next message
Alexander R is currently offline Alexander RFriend
Messages: 211
Registered: July 2013
Senior Member
Ah sorry i forgot something in the grammar:


OpCall:
reference = [Operation] ('(' (expression+=Expression ("," expression+=Expression)*)? ')' )?


the reference should look like:
myOp(new B(), "asdf")


Re: Customize IQualifiedNameProvider Problem [message #1514932 is a reply to message #1514931] Wed, 17 December 2014 18:34 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
why do you index the function by its complete name then?

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize IQualifiedNameProvider Problem [message #1514941 is a reply to message #1514932] Wed, 17 December 2014 18:44 Go to previous messageGo to next message
Alexander R is currently offline Alexander RFriend
Messages: 211
Registered: July 2013
Senior Member
the problem is the folowing situation.

	class Tester {
		f (x: Integer){
}
  		f (x: Boolean){
}

		public useF(){ 
			 f(true);
		}    
	}


My ScopeProvider works correct for this situation. Means both method-names are in the scope ( I debuged it while building the scope) . But they have the same name.
So the Scope::ScopesFor().. gives me only the first operation in the scope. And this is the one with the integer parameter.
--->So the booleal-meathon is not in the scope and the reference f(true); can't match the right method.

That is my big problem...
Re: Customize IQualifiedNameProvider Problem [message #1514947 is a reply to message #1514941] Wed, 17 December 2014 18:48 Go to previous messageGo to next message
Alexander R is currently offline Alexander RFriend
Messages: 211
Registered: July 2013
Senior Member
I thought:
When I change the qualifiedName of Operations to its signature, both will appear in the scope of a reference...
Re: Customize IQualifiedNameProvider Problem [message #1514948 is a reply to message #1514947] Wed, 17 December 2014 18:49 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
no you have to ensure that yourself.

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize IQualifiedNameProvider Problem [message #1514957 is a reply to message #1514948] Wed, 17 December 2014 18:59 Go to previous messageGo to next message
Alexander R is currently offline Alexander RFriend
Messages: 211
Registered: July 2013
Senior Member
But how can I workaround this fact?

Quote:
A scope does not export two objects with the same name in the same scope-level


I took this from Sebastian Zarnekow: http://zarnekow.blogspot.fr/2009/01/xtext-corner-2-linking-and-scoping.html
Re: Customize IQualifiedNameProvider Problem [message #1515513 is a reply to message #1514957] Thu, 18 December 2014 06:08 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
Are your ops defined globally? Do you allow polymorphic overloading ?

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize IQualifiedNameProvider Problem [message #1515522 is a reply to message #1515513] Thu, 18 December 2014 06:16 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
And how are your types defined? Do they only have simple names?

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize IQualifiedNameProvider Problem [message #1515624 is a reply to message #1515522] Thu, 18 December 2014 08:16 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
you can adapt IDefaultResourceDescriptionStrategy and (for local elements) ImportedNamespaceAwareLocalScopeProvider
to store the signature in the user data in the index and use that userdata in the scoping to filter

of course this will not work in content assist since you dont know the params yet

do you care about content assist and error messages as well?
Depending on That you may adapt DefaultLinkingService and Validator as well



Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize IQualifiedNameProvider Problem [message #1515717 is a reply to message #1515624] Thu, 18 December 2014 10:03 Go to previous messageGo to next message
Alexander R is currently offline Alexander RFriend
Messages: 211
Registered: July 2013
Senior Member
Hi Christian ,

thanks a lot for your posts. Here some facts to my DSL:


- Operations are not defiend globaly, they may be inhereted from other classes
- Operations of classes, are of course visible and accessable inside the class
- Operation overloading is allowed, Ops with same name but different signatures are valid ( different types taken into account)
- Types are calculated via the Xtext-Typesyste-Framework (from Voelter):
https://code.google.com/a/eclipselabs.org/p/xtext-typesystem/
-->But for the QualifiedName-Calculation I would only use the String image (ex. 'int') of the primitive types and the param-name of the referenced types

What I want to do is to allow access to opearions with same name, but different types (overloaded ops)

Contentassist and validation are necessary ( and works already..)

Maybe I can just filter the operations with the right params while calculating the scope?

Thanks for your help,

Alex
Re: Customize IQualifiedNameProvider Problem [message #1515752 is a reply to message #1515717] Thu, 18 December 2014 10:41 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
yes you can filter within the scope provider
have a look at

Model:
	elements+=Element*;
	
Element:
	Operation | Call
;

enum DataType:
	string | int | boolean
;

Operation:
	"def" name=ID "(" ( parameter+=Parameter ("," parameter+=Parameter )*)? ")"
;

Parameter:
	type=DataType name=ID
;

Call:
	"call" operation=[Operation] "(" (parameter+=Expression (","parameter+=Expression)*)? ")"
;

Expression:
	StringLiteral | IntLiteral | BooleanLiteral
;

StringLiteral:
	value=STRING
;

IntLiteral:
	value=INT
;

BooleanLiteral:
	{BooleanLiteral} (value?='true' | 'false')
;


class MyDslImportedNamespaceAwareLocalScopeProvider extends ImportedNamespaceAwareLocalScopeProvider {
	
	override ISelectable internalGetAllDescriptions(Resource resource) {
		val Iterable<EObject> allContents = new Iterable<EObject>(){
			override Iterator<EObject> iterator() {
				return EcoreUtil.getAllContents(resource, false);
			}
		}; 
		val Iterable<IEObjectDescription> allDescriptions = scopedElementsFor(allContents, qualifiedNameProvider);
		return new MultimapBasedSelectable(allDescriptions);
	}
	
	def <T extends EObject> Iterable<IEObjectDescription> scopedElementsFor(Iterable<? extends T> elements,
			Function<T, QualifiedName> nameComputation) {
		val Iterable<IEObjectDescription> transformed = Iterables.transform(elements,
				new Function<T, IEObjectDescription>() {
					override IEObjectDescription apply(T from) {
						val QualifiedName qualifiedName = nameComputation.apply(from);
						var Map<String,String> data = null
						if (from instanceof Operation) {
							data = <String,String>newHashMap("signature" -> from.parameter.map[type.literal].join(","))
						}
						if (qualifiedName != null)
							return new EObjectDescription(qualifiedName, from, data);
						return null;
					}
				});
		return Iterables.filter(transformed, Predicates.notNull());
	}
	
}


class MyDslResourceDescriptionStrategy extends DefaultResourceDescriptionStrategy {
	
	private final static Logger LOG = Logger.getLogger(MyDslResourceDescriptionStrategy)
	
	override createEObjectDescriptions(EObject eObject, IAcceptor<IEObjectDescription> acceptor) {
		if (eObject instanceof Operation) {
			createOperationDescriptions(eObject,acceptor)
		}
		super.createEObjectDescriptions(eObject, acceptor)
	}
	
	def boolean createOperationDescriptions(Operation eObject, IAcceptor<IEObjectDescription> acceptor) {
		if (getQualifiedNameProvider() == null)
			return false;
		try {
			val QualifiedName qualifiedName = getQualifiedNameProvider().getFullyQualifiedName(eObject);
			if (qualifiedName != null) {
				val data = newHashMap
				data.put("signature", eObject.parameter.map[type.literal].join(","))
				acceptor.accept(EObjectDescription.create(qualifiedName, eObject,data));
			}
		} catch (Exception exc) {
			LOG.error(exc.getMessage(), exc);
		}
		return true;
	}
	
}


class MyDslScopeProvider extends AbstractDeclarativeScopeProvider {

	def IScope scope_Call_operation(Call ctx, EReference ref) {
		new FilteringScope(delegateGetScope(ctx,ref)) [
			val signature = ctx.parameter.map[p|
				val x = switch(p) {
					StringLiteral: DataType.STRING
					BooleanLiteral: DataType.BOOLEAN
					IntLiteral: DataType.INT
				}
				x.literal
			].join(",")
			getUserData("signature") == signature
		]
	}

}


public class MyDslRuntimeModule extends org.xtext.example.mydsl2.AbstractMyDslRuntimeModule {

	public Class<? extends IDefaultResourceDescriptionStrategy> bindIDefaultResourceDescriptionStrategy() {
		return MyDslResourceDescriptionStrategy.class;
	}
	
	public void configureIScopeProviderDelegate(Binder binder) {
		binder.bind(IScopeProvider.class).annotatedWith(Names.named(AbstractDeclarativeScopeProvider.NAMED_DELEGATE)).to(MyDslImportedNamespaceAwareLocalScopeProvider.class);
	}
	
}



(but as i said this wont work in content assist Sad )!!!
thus you may need to do this in the linking service as i said

is there a reason you cannot/want not to use Xbase?


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize IQualifiedNameProvider Problem [message #1515821 is a reply to message #1514718] Thu, 18 December 2014 12:03 Go to previous messageGo to next message
Alexander R is currently offline Alexander RFriend
Messages: 211
Registered: July 2013
Senior Member
Hi,

first of all thanks for your time and your help!

This project is "grown" like that. It depends on an official specification...
I tried to limit the dependence to other DSLs or Frameworks as much as possible and try to implement the grammar and metamodel the way the spec. wants it..that is a hard way to go..

Btw. What version of xtend did you used in your example code? I am still usig xtend 2.5.4 and have so problems with inner classes (?) like:

new Iterable<EObject>(){
			override Iterator<EObject> iterator() {
				return EcoreUtil.getAllContents(resource, false); 
			}
		}; 


Best regards,
Alex

[Updated on: Fri, 26 December 2014 15:26]

Report message to a moderator

Re: Customize IQualifiedNameProvider Problem [message #1515827 is a reply to message #1515821] Thu, 18 December 2014 12:09 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
hi i use 2.7.3 but it should be no problem to factor that out or use a closure instead of the inner class or refactor it to java

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize IQualifiedNameProvider Problem [message #1515836 is a reply to message #1515827] Thu, 18 December 2014 12:15 Go to previous messageGo to next message
Alexander R is currently offline Alexander RFriend
Messages: 211
Registered: July 2013
Senior Member
Great!
I will try it out.
Re: Customize IQualifiedNameProvider Problem [message #1515862 is a reply to message #1515836] Thu, 18 December 2014 12:46 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
Here is a Quick draft for the linking service (dont adapt the scope provider in that case)

class MyDslLinkingService extends DefaultLinkingService {

	@Inject
	@LinkingScopeProviderBinding
	private IScopeProvider scopeProvider;

	@Inject
	private Provider<ImportedNamesAdapter> importedNamesAdapterProvider;

	@Inject
	private LinkingHelper linkingHelper;

	@Inject
	private IQualifiedNameConverter qualifiedNameConverter;

	override getLinkedObjects(EObject context, EReference ref, INode node) throws IllegalNodeException {
		val o = NodeModelUtils.findActualSemanticObjectFor(node)
		println(o)
		if (o instanceof Call) {
			val signature = o.parameter.map [ p |
				val x = switch (p) {
					StringLiteral: DataType.STRING
					BooleanLiteral: DataType.BOOLEAN
					IntLiteral: DataType.INT
				}
				x.literal
			].join(",")

			val EClass requiredType = ref.getEReferenceType();
			if (requiredType == null)
				return Collections.<EObject>emptyList();

			val String crossRefString = getCrossRefNodeAsString(node);
			if (crossRefString != null && !crossRefString.equals("")) {
				val IScope scope = getScope(context, ref);
				val QualifiedName qualifiedLinkName = qualifiedNameConverter.toQualifiedName(crossRefString);
				val eObjectDescriptions = scope.getElements(qualifiedLinkName);
				for (eObjectDescription : eObjectDescriptions) {
					if (eObjectDescription != null && eObjectDescription.getUserData("signature") == signature)
						return Collections.singletonList(eObjectDescription.getEObjectOrProxy());
				}
				
			}
			return Collections.emptyList();
		}

		super.getLinkedObjects(context, ref, node)

	}

}


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize IQualifiedNameProvider Problem [message #1515898 is a reply to message #1515862] Thu, 18 December 2014 13:29 Go to previous messageGo to next message
Alexander R is currently offline Alexander RFriend
Messages: 211
Registered: July 2013
Senior Member
It's magical! Wink

No really, thank you.
I spent the whole week trying to figure this out!
I will try to adapt it in my project.
Re: Customize IQualifiedNameProvider Problem [message #1547265 is a reply to message #1514718] Mon, 05 January 2015 10:21 Go to previous messageGo to next message
Alexander R is currently offline Alexander RFriend
Messages: 211
Registered: July 2013
Senior Member
Hello,

I added the features you mentioned and it works. But only if my own ScopeProvider is doing nothing. The problem is, I already implemented a scope strategy. For inheritance of operations and other scenarios ..

Is it possible to customize the MyDslLinkingService and to keep an own implementation of the AbstractDeclarativeScopeProvider?

~Alex

[Updated on: Mon, 05 January 2015 10:34]

Report message to a moderator

Re: Customize IQualifiedNameProvider Problem [message #1547285 is a reply to message #1547265] Mon, 05 January 2015 10:37 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
the linking service calls the scope provider. you only have to make sure the objects in scope contain the correct metadata.
drive into the Scopes.scopeFor methods to see how the IEObjectDescriptions are created. add the metadata there as well!!!


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize IQualifiedNameProvider Problem [message #1547339 is a reply to message #1547285] Mon, 05 January 2015 11:19 Go to previous messageGo to next message
Alexander R is currently offline Alexander RFriend
Messages: 211
Registered: July 2013
Senior Member
Hi,

so I have to calculate the userdata of IEObjectDescriptions in my own "MyScopeProvider extends AbstractDeclarativeScopeProvider" for the right objects in the right scope? But do I still have to
implement an own ImportedNamespaceAwareLocalScopeProvider when it is never used?

Thanks
Re: Customize IQualifiedNameProvider Problem [message #1547352 is a reply to message #1547339] Mon, 05 January 2015 11:26 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
if you do no adapt scoping at all

- ImportedNamespaceAwareLocalScopeProvider is used for elements of the same file
- IDefaultResourceDescriptionStrategy is used for the xtext index (other resources)

so the question is: what do you actually do in your scope provider?


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize IQualifiedNameProvider Problem [message #1547374 is a reply to message #1547352] Mon, 05 January 2015 11:42 Go to previous messageGo to next message
Alexander R is currently offline Alexander RFriend
Messages: 211
Registered: July 2013
Senior Member
My ScopeProvider handles two scenarios:

1. Scope for blocks (in methods)
2. Calculats the scope for member-access (Traverses superclasses to find all accessable properties and operations)

The calculation of the right scope for these two scenarios is working and I want to keep it that way.
Re: Customize IQualifiedNameProvider Problem [message #1547381 is a reply to message #1547374] Mon, 05 January 2015 11:45 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
but why do you need then meta data based filtering at all if you know the scope anyway?

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize IQualifiedNameProvider Problem [message #1547389 is a reply to message #1547381] Mon, 05 January 2015 11:53 Go to previous messageGo to next message
Alexander R is currently offline Alexander RFriend
Messages: 211
Registered: July 2013
Senior Member
cause I wanted to allow method-overriding. Look at this example:

	class Tester {
		f (x: Integer){
}
  		f (x: Boolean){
}

		public useF(){ 
			 this.f(true);
		}    
	}


The scope for the memberaccess is calculated the right way:
this.f --> both methods [f(int), f(bool)] are in the scope of the "member-reference".
But with the default implementation, the linker uses only the first referenceble element f(int) in the scope, and f(bool) may not be referenced!

Thanks my problem. I just want to allow "polymorphic overloading-calls".
Re: Customize IQualifiedNameProvider Problem [message #1547402 is a reply to message #1547389] Mon, 05 January 2015 12:04 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
then you have to adapt the scope method as i suggested before

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize IQualifiedNameProvider Problem [SOLVED] [message #1549122 is a reply to message #1547402] Tue, 06 January 2015 10:38 Go to previous message
Alexander R is currently offline Alexander RFriend
Messages: 211
Registered: July 2013
Senior Member
Problem solved in two steps. Both Steps are performed in an customized ScopeProvider after calculating the right scope:


1. Step: Create a IEObjectDescriptionList (with userdata) out of an elementsList
def <T extends EObject> Iterable<IEObjectDescription> scopedElementsForWithSignature(Iterable<? extends T> elements,
		Function<T, QualifiedName> nameComputationFunction) {

		val Iterable<IEObjectDescription> formatedOperations = Iterables.transform(elements,
			new Function<T, IEObjectDescription>() {

				override IEObjectDescription apply(T from) {
					val QualifiedName qualifiedName = nameComputationFunction.apply(from);

					//this is the arbitrary user data of an EOject in an EObjectDescription
					var Map<String, String> data = null
					if (from instanceof Operation) {
						val sig = QualifiedNameFormatter.createOperationSignature(from)
						data = <String, String>newHashMap("signature" -> sig)
					}
					if (qualifiedName != null)
						return new EObjectDescription(qualifiedName, from, data);
					return null;
				}
			});
		return Iterables.filter(formatedOperations, Predicates.notNull());
	}



2. Step: Create the Scope
val eObjectDescrs = createEObjectDesrcList(elements, QualifiedName.wrapper(SimpleAttributeResolver.NAME_RESOLVER));
val finalScope =  new SimpleScope(parentScope, innerScopeElementsIObjectDescr);


Thanks a lot for your help Christian!

~Alex
Previous Topic:implement &quot;continue&quot; and &quot;break&quot; with Xbase
Next Topic:multi-module maven build
Goto Forum:
  


Current Time: Thu Apr 25 05:44:47 GMT 2024

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

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

Back to the top