Skip to main content

Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Content assist when model is incomplete (Can the parser be helped to create a better model as base for content assist)
Content assist when model is incomplete [message #1724265] Mon, 22 February 2016 16:11 Go to next message
Nils Kronqvist is currently offline Nils KronqvistFriend
Messages: 10
Registered: July 2009
Junior Member

I have a problem when wanting to create a proposal based on an incomplete model: If having the code as below (example 1) and invoking Ctrl-space as indicated -- as I have overidden the method

completeModelQuery_Methods(ModelQuery model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor)

in a AbstractQuickSvtProposalProvider subclass, it gets called as expected. The "model" parameter has a rootObject named "point" and one entry in the methods list named "Rectangle" -- makes sense, the parser is doing it's best to resolve the incomplete model. As the "point" variable is defined in the topmost statement (RootVarDefinition), and I want the definition type (varType -- i.e. "Point") - I expected that the rootObject (a VarDefinition cross-reference), would be resolved to the VarDefinition in the RootVarDefinition statement.

BUT for some reason the rootObject of the model parameter is contained in an instance of a GenericVarDefinition with varType value = "rect" , varValue = null - and I can see no reliable way of getting the correct VarDefinition.

What would be the best solution to make the parser less confused in case of example 1 below ..?

BTW: Example 2 below works as expected, as the parser is helped by the statement not including a "point" ..

Example 1: Not working ...
Root: Point point {
  if (point.[Ctrl-space]
  Rectangle rect = point.bounds;

Example 2: Working ...

Root: Point point {
  if (point.[Ctrl-space]
  int i = 0;
  Rectangle rect = point.bounds;

Grammar (simplified and abbreviated ..):
	rootVarDefinition=RootVarDefinition '{'

	'Root:' varType=ID varDefinition=VarDefinition

	GenericVarDefinition | DefIfElseStatement

	'if' '(' booleanStatement=BooleanStatement ')' '{'
	('else' '{'

	varType=ID varDefinition=VarDefinition '=' varValue=Operand ';'

	(opAlt1=ModelQuery | opAlt2=SimpleValue) (arithOp=ArithOp nextOp=Operand)?

	valueInt=INT | valueNull='null' | valueString=STRING

	rootObject=[VarDefinition] ('.' methods+=Method)*

	methodName=ID ( '(' methodParameter=Operand ')')?

Re: Content assist when model is incomplete [message #1724417 is a reply to message #1724265] Tue, 23 February 2016 19:22 Go to previous messageGo to next message
Sven Efftinge is currently offline Sven EfftingeFriend
Messages: 83
Registered: January 2016
Location: Kiel

It's hard to tell what's going on here as the grammar is too much abbreviated.
Could you please provide a working grammar where the situation can be reproduced and attach it to a bugzilla?
Re: Content assist when model is incomplete [message #1725141 is a reply to message #1724417] Tue, 01 March 2016 09:00 Go to previous message
Nils Kronqvist is currently offline Nils KronqvistFriend
Messages: 10
Registered: July 2009
Junior Member
Found the issue. For other reasons the custom implementation of the scope provider collected the VarDefinitions into a Map with the name of the definition as key - so the first correct definition was overwritten by a second bad one. If instead allowing all VarDefinitions to be added to the scope, it worked as expected.

So the only IMO odd thing is why the "bad" VarDefinition is constructed at all .. Again; having the code below ..
Root: Point point {
  if (point.
  int x = point.routes.size;

and adding collection and logging in a scope provider ..
  public IScope getScope(EObject context, EReference reference) {
    Class<?> refC = reference.getContainerClass();
    if (refC.equals(ModelQuery.class)) {
      return Scopes.scopeFor(getDefinitions(context));
    return super.getScope(context, reference);

  private List<VarDefinition> getDefinitions(EObject context) {
    List<VarDefinition> defs = new ArrayList<>();
    ModelRoot root = getModelRoot(context);
    RootVarDefinition rootVarDef = root.getRootVarDefinition();
    System.out.println("Found def named: " + rootVarDef.getVarDefinition().getName() + " type: "
        + rootVarDef.getVarType());
    for (Content content : root.getContents()) {
      if (content instanceof GenericVarDefinition) {
        GenericVarDefinition genDef = (GenericVarDefinition) content;
        System.out.println("Found def named: " + genDef.getVarDefinition().getName() + " type: "
            + genDef.getVarType());
    return defs;

  private ModelRoot getModelRoot(EObject context) {
    if (context instanceof ModelRoot) {
      return (ModelRoot) context;
    } else {
      return getModelRoot(context.eContainer());

gives this result:

Found def named: point type: Point
Found def named: point type: x
Found def named: size type: routes

The bold def is "bad" .. I guess my question is; is this expected? And if so, is there any way of telling that this is not a valid def?

Debugged a bit and found that the Xtext code handles duplicate names by just picking the first one. In org.eclipse.xtext.scoping.impl.AbstractScope:
	protected IEObjectDescription getSingleLocalElementByName(QualifiedName name) {
		Iterable<IEObjectDescription> result = getLocalElementsByName(name);
		Iterator<IEObjectDescription> iterator = result.iterator();
		if (iterator.hasNext())
		return null;

Might be just good enough I guess ..


Previous Topic:Ecore model not properly registered
Next Topic:Use Formatter1 in Xtext 2.9
Goto Forum:

Current Time: Sat Jul 02 00:11:49 GMT 2022

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

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

Back to the top