Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Referenced DSL-Files are not recognized on clean
Referenced DSL-Files are not recognized on clean [message #1838543] Mon, 01 March 2021 09:45 Go to next message
Christian Sodomka is currently offline Christian SodomkaFriend
Messages: 19
Registered: May 2019
Junior Member
We have a DSL where the parameters of calls are defined in separate Files. Those are normally read and parsed automatically. We also have a validator to check those parameters.
Now when we edit the dsl file containing the call, everything is normal. But if I do a clean, all parameters become red underlined. Debugging reveals that at this stage the definitions of the separate files have not been read yet, hence no validation is possible.
Also the stack trace of an edit validation is completely differend from a clean validation, when setting the halt point inside the validation.
How comes? And what is the solution to this problem?
Though the error goes away after insertion of a blank this behaviour is very confusing for the users. Even in some cases (this cannot always be reproduced) it is necessary to reopen the file, to get rid of thoses false errors.
Re: Referenced DSL-Files are not recognized on clean [message #1838544 is a reply to message #1838543] Mon, 01 March 2021 09:47 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
hi, i wonder how you implement this. if you use normal cross references then all files should be indexed first and then the index data can be used to resolve it.

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Referenced DSL-Files are not recognized on clean [message #1838545 is a reply to message #1838544] Mon, 01 March 2021 09:52 Go to previous messageGo to next message
Christian Sodomka is currently offline Christian SodomkaFriend
Messages: 19
Registered: May 2019
Junior Member
We just have a definition file (*.def) in a separate directory and the program file where the calls reside. This is parsed automatically normally, we did not do any programming here. And normally it works, but not with project clean.
Re: Referenced DSL-Files are not recognized on clean [message #1838547 is a reply to message #1838545] Mon, 01 March 2021 10:27 Go to previous messageGo to next message
Christian Sodomka is currently offline Christian SodomkaFriend
Messages: 19
Registered: May 2019
Junior Member
Here is a junk of code:
	private def void _checkNumberOfArguments(EObject p) {
		var numberArgsGiven = 0
		var numberArgsDefMax = 0
		var numberArgsDefMin = 0
		var EList<Argument> args
		var EList<InParameter> paras
		var EReference ref
		switch (p) {
			Call: {
				args = p.arguments?.arguments
				paras = p.ref?.importedCall.parameter
				ref = TabsPackage.eINSTANCE.call_Arguments
			}
			ProcessCall: {
				args = p.arguments?.arguments
				paras = p.ref?.importedProcesses.parameter
				ref = TabsPackage.eINSTANCE.processCall_Arguments
			}
			Loop: {
				args = p.arguments?.arguments
				paras = p.iterator?.importedIterator.parameter
				ref = TabsPackage.eINSTANCE.loop_Arguments
			}
			default: {
				throw new IllegalArgumentException()
			}
		}
		if (args !== null) {
			numberArgsGiven = args.size;
		}
		if (paras !== null) {
			numberArgsDefMax = paras.size;
			numberArgsDefMin = paras.filter[defaultValue === null].size;
		}
		if ((numberArgsGiven > numberArgsDefMax) || (numberArgsGiven < numberArgsDefMin)) { // number of arguments out of valid range
			if (numberArgsDefMax != numberArgsDefMin) { // optional parameter exist
				error("Die Anzahl der Parameter muss zwischen " + numberArgsDefMin + " und " + numberArgsDefMax + " sein",
					ref, NUMBER_ARGS)
			} else {
				error("Die Anzahl der Parameter muss " + numberArgsDefMin + " sein",
					ref, NUMBER_ARGS)
			}
		}
	}

where args afre the arguments in the source file and ref are the arguments in the definitions. On clean ref stays empty, on normal edit not.
Re: Referenced DSL-Files are not recognized on clean [message #1838549 is a reply to message #1838547] Mon, 01 March 2021 10:42 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
any customizations in scoping?

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Referenced DSL-Files are not recognized on clean [message #1838551 is a reply to message #1838549] Mon, 01 March 2021 11:17 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

It is standard EMF practice when unloading Resources to proxify all references. If a clean is provoking an unload, then a failure to re-resolve references may be at the root of your problem.

Regards

Ed Willink
Re: Referenced DSL-Files are not recognized on clean [message #1838552 is a reply to message #1838551] Mon, 01 March 2021 11:37 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
@Ed Xtext should do this automatically.

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Referenced DSL-Files are not recognized on clean [message #1838554 is a reply to message #1838549] Mon, 01 March 2021 11:41 Go to previous messageGo to next message
Christian Sodomka is currently offline Christian SodomkaFriend
Messages: 19
Registered: May 2019
Junior Member
Yes we did do scoping also. But as it works with editing in general, I think this is not an issue.
Re: Referenced DSL-Files are not recognized on clean [message #1838555 is a reply to message #1838554] Mon, 01 March 2021 11:55 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
the question is: how did you implement scoping? do you do direct index access there.
you might also debug the resolving at
org.eclipse.xtext.linking.impl.DefaultLinkingService.getLinkedObjects(EObject, EReference, INode)


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Referenced DSL-Files are not recognized on clean [message #1838556 is a reply to message #1838555] Mon, 01 March 2021 12:08 Go to previous messageGo to next message
Christian Sodomka is currently offline Christian SodomkaFriend
Messages: 19
Registered: May 2019
Junior Member
We used the following code:
package at.ama.swm.tabs.scoping

import com.google.inject.Inject
import org.eclipse.emf.ecore.EObject
import org.eclipse.xtext.resource.impl.ResourceDescriptionsProvider
import at.ama.swm.tabs.tabs.TabsPackage

class TabsIndex {

	@Inject ResourceDescriptionsProvider rdp

	def getResourceDescription(EObject eObj) {
		val index = rdp.getResourceDescriptions(eObj.eResource)
		index.getResourceDescription(eObj.eResource.URI)
	}

	def getExportedEObjectDescriptions(EObject eObj) {
		eObj.getResourceDescription.getExportedObjects
	}

	def getExportedClassesEObjectDescriptions(EObject eObj) {
		eObj.getResourceDescription.getExportedObjectsByType(TabsPackage.eINSTANCE.project)
	}
}


and

/*
 * generated by Xtext 2.16.0
 */
package at.ama.swm.tabs.scoping

import at.ama.swm.tabs.tabs.Process
import at.ama.swm.tabs.tabs.TabsPackage
import at.ama.swm.tabs.tabs.TabsProcess
import at.ama.swm.tabs.tabs.TabsProgram
import org.eclipse.emf.common.util.BasicEList
import org.eclipse.emf.common.util.EList
import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.EReference
import org.eclipse.xtext.scoping.IScope

/**
 * This class contains custom scoping description.
 * 
 * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#scoping
 * on how and when to use it.
 */
class TabsScopeProvider extends AbstractTabsScopeProvider {

	val ePackage = TabsPackage.eINSTANCE
	
	override getScope(EObject context, EReference reference) {
		
		// Symbols - Variables & In/Out Parameters
		if (reference == ePackage.symbolRef_Value || reference == ePackage.resultRef_Symbol) {
			return scopeForSymbolRef(context)
		}
		// use - only valid in current process
		else if (reference == ePackage.call_Ref) {
			return scopeForUseRef(context)
		}
		else if (reference == ePackage.processCall_Ref) {
			return scopeForUseRef(context)
		}
		else if (reference == ePackage.call_Fqn) {
		}
		// global var defs 		
		else if (reference == ePackage.qualifiedVariable_Struct) {
			return scopeForGlobalRef(context)
		}
		
		return super.getScope(context, reference)
	}
	

	def protected IScope scopeForGlobalRef(EObject context) {
		val container = context.eContainer
		return switch (container) {
			TabsProgram: {
				IgnoreCaseScopes.scopeFor(container.proc.using)
			}
			default: scopeForGlobalRef(container)
		}		
	}


	def protected IScope scopeForUseRef(EObject context) {
		val container = context.eContainer
		return switch (container) {
			TabsProcess: {
				IgnoreCaseScopes.scopeFor(container.using)
			}
			default: scopeForUseRef(container)	
		}
	}

	
	/*
	 * calculate the Scope for Symbol References
	 * Seite 249 im Buch!
	 */
	def protected IScope scopeForSymbolRef(EObject context) {
		val container = context.eContainer
		return switch (container) {
			Process: {
				var EList<EObject> symbolList = new BasicEList()
				symbolList.addAll(container.variables)
				symbolList.addAll(container.parameter)
				IgnoreCaseScopes.scopeFor(symbolList)				
			}
			default: scopeForSymbolRef(container)
		}
	}
	
}



and for ignore case:

/*******************************************************************************
 * Cope of org.eclipse.xtext.scoping.Scopes
 *
 * THE ESSENTIAL DIFFERENCE:
 * SimpleScope() is created with last param boolean ignoreCase set to true
 *
 *******************************************************************************/
package at.ama.swm.tabs.scoping;

import java.util.ArrayList;
import java.util.Map;

import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.resource.EObjectDescription;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.impl.SimpleScope;
import org.eclipse.xtext.util.SimpleAttributeResolver;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;

/**
 * This class contains static utility functions to create and work on {@link IScope} and {@link IEObjectDescription}
 *
 * @author Sven Efftinge - Initial contribution and API
 * @author Jan Koehnlein - introduced QualifiedName
 */
public class IgnoreCaseScopes {

	public static Iterable<IEObjectDescription> selectCompatible(Iterable<IEObjectDescription> exportedObjects, final EClass clazz) {
		return Iterables.filter(exportedObjects, new Predicate<IEObjectDescription>() {
			@Override
			public boolean apply(IEObjectDescription input) {
				return EcoreUtil2.isAssignableFrom(clazz,input.getEClass());
			}
		});
	}

	/**
	 * creates a scope using {@link SimpleAttributeResolver#NAME_RESOLVER} to compute the names and sets
	 * {@link IScope#NULLSCOPE} as parent scope
	 */
	public static IScope scopeFor(Iterable<? extends EObject> elements) {
		return scopeFor(elements, IScope.NULLSCOPE);
	}

	/**
	 * creates a scope using {@link SimpleAttributeResolver#NAME_RESOLVER} to compute the names
	 */
	public static IScope scopeFor(Iterable<? extends EObject> elements, IScope outer) {
		return scopeFor(elements, QualifiedName.wrapper(SimpleAttributeResolver.NAME_RESOLVER), outer);
	}

	/**
	 * creates a scope using the passed function to compute the names and sets the passed scope as the parent scope
	 */
	public static <T extends EObject> IScope scopeFor(Iterable<? extends T> elements,
			final Function<T, QualifiedName> nameComputation, IScope outer) {
		return new SimpleScope(outer,scopedElementsFor(elements, nameComputation), true);
	}

	/**
	 * transforms an {@link Iterable} of {@link EObject}s into an {@link Iterable} of {@link IEObjectDescription}s computing
	 * the {@link EAttribute} 'name' to compute the {@link IEObjectDescription}'s name. If not existent the object is
	 * filtered out.
	 */
	public static Iterable<IEObjectDescription> scopedElementsFor(Iterable<? extends EObject> elements) {
		return scopedElementsFor(elements, QualifiedName.wrapper(SimpleAttributeResolver.NAME_RESOLVER));
	}

	/**
	 * transforms an {@link Iterable} of {@link EObject}s into an {@link Iterable} of {@link IEObjectDescription}s computing
	 * the name of the elements using the passed {@link Function} If the passed function returns null the object is
	 * filtered out.
	 */
	public static <T extends EObject> Iterable<IEObjectDescription> scopedElementsFor(Iterable<? extends T> elements,
			final Function<T, QualifiedName> nameComputation) {
		Iterable<IEObjectDescription> transformed = Iterables.transform(elements,
				new Function<T, IEObjectDescription>() {
					@Override
					public IEObjectDescription apply(T from) {
						final QualifiedName qualifiedName = nameComputation.apply(from);
						if (qualifiedName != null)
							return new EObjectDescription(qualifiedName, from, null);
						return null;
					}
				});
		return Iterables.filter(transformed, Predicates.notNull());
	}

	/**
	 * indexes the IEObject description using the given
	 */
	public static <T> Multimap<T,IEObjectDescription> index(Iterable<IEObjectDescription> descriptions, Function<IEObjectDescription,T> indexer) {
		ArrayList<IEObjectDescription> list = Lists.newArrayList(descriptions);
		LinkedHashMultimap<T, IEObjectDescription> multimap = LinkedHashMultimap.create(list.size(),1);
		for (IEObjectDescription desc : list) {
			multimap.put(indexer.apply(desc), desc);
		}
		return multimap;
	}

	/**
	 * indexes the IEObject description using the given
	 */
	public static Multimap<QualifiedName,IEObjectDescription> index(Iterable<IEObjectDescription> descriptions) {
		return index(descriptions, new Function<IEObjectDescription, QualifiedName>() {
			@Override
			public QualifiedName apply(IEObjectDescription from) {
				return from.getName().toLowerCase();
			}
		});
	}

	public static Iterable<IEObjectDescription> filterDuplicates(Iterable<IEObjectDescription> filtered) {
		Map<QualifiedName, IEObjectDescription> result = Maps.newLinkedHashMap();
		for (IEObjectDescription e : filtered) {
			QualifiedName qualifiedName = e.getName();
			if (result.containsKey(qualifiedName)) {
				result.put(qualifiedName, null);
			} else {
				result.put(qualifiedName, e);
			}
		}
		return Iterables.filter(result.values(), Predicates.notNull());
	}

}
Re: Referenced DSL-Files are not recognized on clean [message #1838557 is a reply to message #1838556] Mon, 01 March 2021 12:10 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
val index = rdp.getResourceDescriptions(eObj.eResource)
here you access the index which is not updated yet but cleaned.

the usual way is to call delegateGetScope and filter it and not to access the index directly.


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

[Updated on: Mon, 01 March 2021 12:11]

Report message to a moderator

Re: Referenced DSL-Files are not recognized on clean [message #1838558 is a reply to message #1838557] Mon, 01 March 2021 12:14 Go to previous messageGo to next message
Christian Sodomka is currently offline Christian SodomkaFriend
Messages: 19
Registered: May 2019
Junior Member
Thanks for the fast analysis. I will forward this to the coder and see if we can fix this.
Re: Referenced DSL-Files are not recognized on clean [message #1838567 is a reply to message #1838558] Mon, 01 March 2021 15:04 Go to previous messageGo to next message
Christian Sodomka is currently offline Christian SodomkaFriend
Messages: 19
Registered: May 2019
Junior Member
Unfortunately this did not work.
The line
val index = rdp.getResourceDescriptions(eObj.eResource)
is not called in the program at all. It is just part of a test routine.
So we don't access the index directly.
What is called, is TabsScopeProvider.getScope. I tried to rename it to delegateGetScope and call its super at the start of the method, just to give it a try. But this did not change anything. Still the reference is not loaded and the ref parameter are void.
Re: Referenced DSL-Files are not recognized on clean [message #1838569 is a reply to message #1838567] Mon, 01 March 2021 15:42 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
then you should debug the DefaultLinkingService and its interaction with the scoping

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Referenced DSL-Files are not recognized on clean [message #1838691 is a reply to message #1838569] Wed, 03 March 2021 16:37 Go to previous messageGo to next message
Christian Sodomka is currently offline Christian SodomkaFriend
Messages: 19
Registered: May 2019
Junior Member
After long debugging I found out, that Xtext/Eclipse did not resolve proxy-objects correctly. After resolving them by hand, everything worked.
Here is the altered code:

@Check
def checkNumberOfProcessArguments(Process p) {
var numberArgsGiven = 0
var numberArgsDefMin = 0
var numberArgsDefMax = 0
if (p.parameter !== null) {
numberArgsGiven = p.parameter.size;
}
if (p.process !== null) {
if (p.process.eIsProxy) { // resolve proxy
var XtextResourceSet rs = new XtextResourceSet();
rs.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, java.lang.Boolean.TRUE);
p.process = p.process.resolve(rs) as ProcessDefinition
}
numberArgsDefMax = p.process.parameter.size;
numberArgsDefMin = p.process.parameter.filter[defaultValue === null].size;
/* add all out-parameters also */
if (p.process.result !== null) {
numberArgsDefMax += p.process.result.results.size;
numberArgsDefMin += p.process.result.results.size;
}
}
if ((numberArgsGiven > numberArgsDefMax) || (numberArgsGiven < numberArgsDefMin)) {
if (numberArgsDefMax != numberArgsDefMin) {
error(
"Die Anzahl der Parameter muss zwischen " + numberArgsDefMin + " und " + numberArgsDefMax + " sein",
p, TabsPackage.eINSTANCE.process_Parameter, NUMBER_ARGS)
} else {
error("Die Anzahl der Parameter muss " + numberArgsDefMin + " sein",
p, TabsPackage.eINSTANCE.process_Parameter, NUMBER_ARGS)
}
}
}
Re: Referenced DSL-Files are not recognized on clean [message #1838692 is a reply to message #1838691] Wed, 03 March 2021 17:13 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
all proxies should resolve automatically when you access them.
if not, there must be another problem.


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Referenced DSL-Files are not recognized on clean [message #1838699 is a reply to message #1838692] Wed, 03 March 2021 20:00 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
@Christian No. This is what caught me out a few years ago when I first encountered it. Normal model proxies are typically resolved by the body of getXXX(). But metamodel proxies underlying e.g. eClass() are not. It is necessary to reload the metamodel.

Regards

Ed
Re: Referenced DSL-Files are not recognized on clean [message #1838736 is a reply to message #1838692] Thu, 04 March 2021 10:24 Go to previous messageGo to next message
Christian Sodomka is currently offline Christian SodomkaFriend
Messages: 19
Registered: May 2019
Junior Member
But apparently it does not resolve. See uploads, fist without resolving, second with.

PS: It happens not always but in some cases.

[Updated on: Thu, 04 March 2021 10:56]

Report message to a moderator

Re: Referenced DSL-Files are not recognized on clean [message #1838737 is a reply to message #1838699] Thu, 04 March 2021 10:25 Go to previous messageGo to next message
Christian Sodomka is currently offline Christian SodomkaFriend
Messages: 19
Registered: May 2019
Junior Member
What do you mean by reloading the Metamodel?
Re: Referenced DSL-Files are not recognized on clean [message #1838738 is a reply to message #1838737] Thu, 04 March 2021 10:44 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
then you should debug the linking to find out why it does not resolve

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Referenced DSL-Files are not recognized on clean [message #1838744 is a reply to message #1838738] Thu, 04 March 2021 12:00 Go to previous message
Christian Sodomka is currently offline Christian SodomkaFriend
Messages: 19
Registered: May 2019
Junior Member
This is not my job, as this is not my software. I am happy to have a fix for my problem.
Previous Topic:Eclipse does not recognize dsl file after generation
Next Topic:Mismatched character
Goto Forum:
  


Current Time: Fri Mar 29 05:33:17 GMT 2024

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

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

Back to the top