Xtext problem referencing grammar A from validator of grammar B

Xtext problem referencing grammar A from validator of grammar B



In Xtext, how do I follow a reference from grammar B to grammar A, within a validator of grammar B (which is in the ui-plugin)? Consider the following example.



Grammar A is org.xtext.people.People


org.xtext.people.People


grammar org.xtext.people.People with org.eclipse.xtext.common.Terminals

generate people "http://www.xtext.org/people/People"

People:
people+=Person*;

Person:
'person' name=ID ';';



and an instance


person Alice citizenship "MN"; id "12345";
person Bob citizenship "CH"; id "54321";
person Malice citizenship "XXX"; id "66666";



At an airport, entries of people are recorded.


enter Alice;
enter Bob;
enter Malice;



Entries are modelled with a second grammar B org.xtext.entries.Entries


org.xtext.entries.Entries


grammar org.xtext.entries.Entries with org.eclipse.xtext.common.Terminals

generate entries "http://www.xtext.org/entries/Entries"
import "http://www.xtext.org/people/People"

Entries:
entries+=Entry*;

Entry:
'enter' person=[Person] ';';



After ensuring that the Eclipse project org.xtext.entries has the project org.xtext.people on it's classpath, and ensuring that the org.xtext.entries plugin has the org.xtext.people as a dependency, all works as expected.


org.xtext.entries


org.xtext.people


org.xtext.entries


org.xtext.people



There is a travel ban on people from country XXX, although certain deserving people are excluded. Only the CIA knows who is excluded from the ban. Entries must not be allowed for people from XXX unless excluded.



The updated grammar is


grammar org.xtext.entries.Entries with org.eclipse.xtext.common.Terminals

generate entries "http://www.xtext.org/entries/Entries"


import "http://www.xtext.org/people/People"

Entries:
entries+=Entry*;

Entry:
travelBanOverride=TravelBanOverride?
'enter' person=[Person] ';';

TravelBanOverride: '@TravelBanOverride' '(' code=STRING ')';



with validator


package org.xtext.entries.validation

import org.eclipse.xtext.validation.Check
import org.xtext.entries.entries.EntriesPackage
import org.xtext.entries.entries.Entry
import org.xtext.entries.CIA

class EntriesValidator extends AbstractEntriesValidator

public static val BAN = 'BAN'
public static val ILLEGAL_OVERRIDE = 'ILLEGAL_OVERRIDE'

@Check
def checkBan(Entry entry)
if (entry.person.citizenship == "XXX")
if (entry.travelBanOverride === null)
error('Violation of Travel Ban', EntriesPackage.Literals.ENTRY__PERSON, BAN)

else
val overridecode = entry.travelBanOverride.code;
val valid = CIA.valid(entry.person.name, entry.person.id, overridecode)
if (!valid)
error('Illegal override code', EntriesPackage.Literals.ENTRY__TRAVEL_BAN_OVERRIDE, ILLEGAL_OVERRIDE)










where the driver for the external CIA web-app is modelled for example by


package org.xtext.entries;

public class CIA


public static boolean valid(String name, String id, String overrideCode)
System.out.println("UNValid["+name+","+overrideCode+"]");
return name.equals("Malice") && id.equals("66666") && overrideCode.equals("123");





The validations work as expected.



I now wish to provided a quick-fix for BAN, that checks for an override code from the CIA.


BAN


package org.xtext.entries.ui.quickfix

import org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider
import org.eclipse.xtext.ui.editor.quickfix.Fix
import org.xtext.entries.validation.EntriesValidator
import org.eclipse.xtext.validation.Issue
import org.eclipse.xtext.ui.editor.quickfix.IssueResolutionAcceptor
import org.xtext.entries.entries.Entry
import org.xtext.entries.Helper

class EntriesQuickfixProvider extends DefaultQuickfixProvider

@Fix(EntriesValidator.BAN)
def tryOverride(Issue issue, IssueResolutionAcceptor acceptor)
val entry = element as Entry
// val person = entry.person // no such attribute
//val person = Helper.get(entry); // The method get(Entry) from the type Helper refers to the missing type Object
]




The first commented line does not compile: there is no attribute person. The second commented line is an attempt to solve the problem by getting a helper class in org.xtext.entries to get the person, but this does not compile either, giving a "The method get(Entry) from the type Helper refers to the missing type Object" error message.


person


org.xtext.entries



For completeness, here is that helper.


package org.xtext.entries

import org.xtext.people.people.Person
import org.xtext.entries.entries.Entry

class Helper

static def Person get(Entry entry)
return entry.person;





Further, entry.travelBanOverride compiles fine, but entry.person does not. Clicking on Entry in Eclipse takes one to the expected code, which has both travelBanOverride and person.


entry.travelBanOverride


entry.person


travelBanOverride


person



The issue does not occur with a Java class in the same project and package.


package org.xtext.entries.ui.quickfix;

import org.xtext.entries.entries.Entry;
import org.xtext.people.people.Person;

public class Test

public static void main(String args)
Entry entry = null;
Person p = entry.getPerson();




Rewriting the quickfix in Java solves the problem.


package org.xtext.entries.ui.quickfix;

import org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider;
import org.eclipse.xtext.ui.editor.quickfix.Fix;
import org.xtext.entries.validation.EntriesValidator;
import org.eclipse.xtext.validation.Issue;
import org.eclipse.xtext.ui.editor.quickfix.IssueResolutionAcceptor;
import org.xtext.entries.entries.Entry;
import org.xtext.entries.Helper;
import org.eclipse.xtext.ui.editor.model.edit.IModificationContext;
import org.eclipse.xtext.ui.editor.model.edit.ISemanticModification;
import org.eclipse.emf.ecore.EObject;
import org.xtext.entries.entries.Entry;
import org.xtext.people.people.Person;

public class EntriesQuickfixProvider extends DefaultQuickfixProvider



@Fix(EntriesValidator.BAN)
public void tryOverride(final Issue issue, IssueResolutionAcceptor acceptor)
acceptor.accept(issue,
"Try to override",
"Override",
"override.gif",
new ISemanticModification()
public void apply(EObject element, IModificationContext context)
Entry entry = (Entry) element;
System.out.println(entry.getPerson());


);







i really cannot follow your issue: if you import the right Entry class then there should be a entry.person. for me it looks like there is a error in how you reference the dsls from each other. are you sure you added references to the manifest in the correct way (added it to required bundles)? you talk about project on the classpath. maybe you did the wrong thing
– Christian Dietrich
Sep 3 at 21:02






"val entry = element as Entry" complies fine. If I click on Entry it takes me to the definition with the expected expected method getPerson. But the compiler will have none of it. Just to double check, following a reference from the ui project should be no different to following it from the primary project. There is no well-known/obvious reason for it not to be so?
– fundagain
Sep 3 at 21:24






entry.travelBanOverride compiles fine, but entry.person does not. Clicking on Entry in Eclipse takes one to the expected code, which has both travelBanOverride and person. I have updated the OP to reflect this.
– fundagain
Sep 3 at 22:23


entry.travelBanOverride


entry.person


travelBanOverride


person





It appears that the Java compiler has no problem. I have updated the OP with an example. Will try to write the quickfix in Java and see if this helps.
– fundagain
Sep 3 at 22:47





Rewriting the quickfix in Java solves the problem. I have updated the OP.
– fundagain
Sep 3 at 23:10




1 Answer
1



My mistake is the following.



After ensuring that the Eclipse project org.xtext.entries has the
project org.xtext.people on it's classpath, and ensuring that the
org.xtext.entries plugin has the org.xtext.people as a dependency, all
works as expected.



The org.xtext.entries.ui ui-plugin must also have the org.xtext.people on its Java (Eclipse project) build path. Exporting and making a plugin-dependency it not enough.


org.xtext.entries.ui


org.xtext.people



Note that this setting should be made early, before crafting the quick-fix, because the Xtend editor has refreshing issues.



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Some of your past answers have not been well-received, and you're in danger of being blocked from answering.



Please pay close attention to the following guidance:



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)