Skip to main content



      Home
Home » Modeling » TMF (Xtext) » Helping Xtext to resolve cross references across several files
Helping Xtext to resolve cross references across several files [message #819768] Tue, 13 March 2012 05:58 Go to next message
Eclipse UserFriend
I'm writing a DSL for i18n. The grammar is like this:

I18nDomainModel: {I18nDomainModel}
	( 
                (
			baseLanguage+=BaseLanguage
		) | (
			translations+=Translation
		)
	)*
;

BaseLanguage:
	'base-language' locale=ID '{'
		(
			( imports+=Import ) 
			| ( messages+=BaseMessage )
		)*
	'}'
;

BaseMessage:
	(comment=ML_COMMENT)?
	name=ID
	( '(' (parameters+=ParameterType)* ')' )?
	':' text=STRING
;

Translation:
	'translations' locale=ID '{'
		( messages+=Message )*
	'}'
;

Message:
	(comment=ML_COMMENT)?
	base=[BaseMessage]
	':' text=STRING
;


Basically, you have a block which defines the messages and the parameters that you can use and then you have several blocks with translations for each language.

The messages in the translation blocks (Message) contain cross references to BaseMessage.

This works well if everything is in a single file but for many messages, this becomes unwieldy.

I want to split the files. The URI of the base file is the URI of the translation without the locale part (so demo_de.i18n needs to read demo.i18n). Assume that I can distinguish base and translation files by some other means which I don't show here to keep the example concise.

How do I tell Xtext to parse the base file and resolve cross references from there?

I want to avoid import statements for base file or similar solutions - the translation files should not contain anything which could confuse the translators.
Re: Helping Xtext to resolve cross references across several files [message #819945 is a reply to message #819768] Tue, 13 March 2012 10:29 Go to previous message
Eclipse UserFriend
To answer my own question, here is my approach:

1. Add/enable this fragment in your Generate*.mwe2 file:

fragment = scoping.ImportURIScopingFragment {}


2. Add this code to *RuntimeModule:

    public Class<? extends IGlobalScopeProvider> bindIGlobalScopeProvider() {
        return ImportUriGlobalScopeProvider.class;
    }

    public Class<? extends ImportUriResolver> bindImportUriResolver() {
        return I18nImportUriResolver.class;
    }
    


The important part is the "I18nImportUriResolver" which works like this:

public class I18nImportUriResolver extends ImportUriResolver {

    private final static Logger log = Logger.getLogger( I18nImportUriResolver.class );

    @Override
    public String apply( EObject from ) {
        
        if (I18nDslPackage.Literals.I1_8N_DOMAIN_MODEL.equals( from.eClass() ) ) {
            I18nDomainModel model = (I18nDomainModel) from;
            return apply( model );
        }
        
        return super.apply( from );
    }
    
    public String apply( I18nDomainModel model ) {
        
        if( I18nDslJavaValidator.isBaseModel( model ) ) {
            return null;
        }
        
        URI uri = I18nDslJavaValidator.getBaseURI( model );
        log.debug( "Importing " + uri );
        
        return uri == null ? null : uri.toString();
    }
}


This checks whether the current node in the model is "I18nDomainModel". If so and if this isn't the base file, then the base URI is created by stripping the locale from the URI and the new URI is returned.

Xtext will then load the resource from this URI and add all exported symbols. Xtext knows which symbols to export since I reference some types with "[]" in my grammar:

base=[BaseMessage]


That means all "BaseMessage" instances defined in the base file will be visible by the content of their "name" field.
Previous Topic:problem with 2.0->2.1 update
Next Topic:Scoping for names with Integer type
Goto Forum:
  


Current Time: Mon Jul 07 04:12:50 EDT 2025

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

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

Back to the top