Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Limiting cross-reference to a single file
Limiting cross-reference to a single file [message #1758920] Tue, 04 April 2017 15:30 Go to next message
Finn Rayment is currently offline Finn RaymentFriend
Messages: 26
Registered: April 2017
Junior Member
Hi all, I'm using the below grammar at the moment:

Model:
	(
	package=PackageDeclaration
	imports+=ImportDeclaration*
	types+=Type*
	)?
;

PackageDeclaration:
	'namespace' name=FQN
;

ImportDeclaration:
	'use' name=FQN
;

TypeType:
	Primitive | TypeRef
;

TypeRef:
	ref=[Type | FQN]
;

Type:
	FunctionType | ClassType | EnumType
;

FunctionType:
	'func' name=ID ':' returnType=TypeType LBRACE
	
	RBRACE
;

ClassType:
	'class' name=ID ('parent' superType=TypeRef)? ('inherits' templates+=TypeRef*)? LBRACE
	
	RBRACE
;

EnumType:
	'enum' name=ID LBRACE
		values+=ID*
	RBRACE
;

/* Terminals and strings. */

Primitive:
	name=('int' |
	'long' |
	'short' |
	'float' |
	'double' |
	'str' |
	'char' |
	'bool' |
	'obj' |
	'byte' |
	'nil')
;

FQN:
	ID ('.' ID)*
;

terminal LBRACE: '{' ;
terminal RBRACE: '}' ;


When I run this, I can happily create something like the following:

func TestFunction: RandomType {

}


But oh no! I get an error, because RandomType doesn't exist. Fair enough, so I'm easily able to define RandomType in the file. This is what I want to happen.

What actually happens, is that I can open up a completely different file, and define RandomType, and the other file will automatically remove the error, because it found a RandomType.

The problem is, my program is able to see across multiple files, which I don't want to happen, unless someone uses the ImportDeclaration function which I have also got in the grammar above. Is there a simple way I can limit the cross-referencing capabilities of Xtext?

Thanks for any and all help. Smile

[Updated on: Tue, 04 April 2017 15:31]

Report message to a moderator

Re: Limiting cross-reference to a single file [message #1758923 is a reply to message #1758920] Tue, 04 April 2017 15:56 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
Can you please elaborate how qualified and non qualified names work in your dsl.
Why do you allow xxxx=[yyyy|FQN] at all and don't use xxxxx=[yyyyyy|ID]


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Limiting cross-reference to a single file [message #1758924 is a reply to message #1758923] Tue, 04 April 2017 16:02 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
Ps maybe you need reshuffel your grammar to
To get implicit parent child imports

Model:
(
package=PackageDeclaration
)?
;

PackageDeclaration:
'namespace' name=FQN
imports+=ImportDeclaration*
types+=Type*;


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Limiting cross-reference to a single file [message #1758932 is a reply to message #1758923] Tue, 04 April 2017 17:16 Go to previous messageGo to next message
Finn Rayment is currently offline Finn RaymentFriend
Messages: 26
Registered: April 2017
Junior Member
To be honest I have no idea.
If you look at my other question here:

https://www.eclipse.org/forums/index.php/t/1085364/

I'm pretty much just trying to incorporate the supposed solution into the grammar.
Re: Limiting cross-reference to a single file [message #1758934 is a reply to message #1758923] Tue, 04 April 2017 17:18 Go to previous messageGo to next message
Finn Rayment is currently offline Finn RaymentFriend
Messages: 26
Registered: April 2017
Junior Member
In the grammar at this moment in time, ID's are only used for naming the types (class, enum and function). The Qualified Names can be used for class parents, and class inherits.

The thing is though, the Qualified Names are created with ID's, so in reality, they work hand-in-hand.
Re: Limiting cross-reference to a single file [message #1758936 is a reply to message #1758934] Tue, 04 April 2017 17:22 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
Can you please share for the other problem a complete sample model.

For this problem: can you ever have a qualified name for a thing that comes from the local file and if yes which are these elements

Can you please share a complete represenative sample model for having 2 files with local and foreign references as well


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Limiting cross-reference to a single file [message #1758941 is a reply to message #1758936] Tue, 04 April 2017 17:30 Go to previous messageGo to next message
Finn Rayment is currently offline Finn RaymentFriend
Messages: 26
Registered: April 2017
Junior Member
Funnily enough sorry, the sample model is this model. I posted them as seperate questions as they refer to different issues entirely.

As for an example in practice, one might do the following:

File 1: first_file.ext
namespace random.folders    // see how this is a FQN?

use random.folders.second_file     // also a FQN

class ChildClass parent second_file.ParentClass {
    // ChildClass MUST be an ID, not a FQN,
    // however parent can be either an ID or a FQN.
    // By definition, the FQN's include ID's anyway.
    
    // There is no actual definition of ParentClass in this file,
    // so I would rather be referencing it like so, instead of just typing:
    //     "parent ParentClass". Because at the moment, it accepts that
    // as valid, which if you compare that to a regular language like Java,
    //   "ParentClass" does not exist in this file, so in reality, it SHOULDN't be correct.

    // the entire "parent" thing here, is a foreign reference.
}



File 2: second_file.ext
namespace random.folders

class ParentClass {
    // Again, "ParentClass" is an ID, not a FQN.
}

// Anything below here is just to represent LOCAL references.

class Test { }

class TestChild parent Test { } // Notice how the parent is technically an ID because its local?


The same thing goes for enums as it does for the class. Names are ID's, parents (which the enum doesnt have) are FQN's.

Hope your able to understand my lack of proper articulation. I appreciate your help.

[Updated on: Tue, 04 April 2017 17:34]

Report message to a moderator

Re: Limiting cross-reference to a single file [message #1758943 is a reply to message #1758936] Tue, 04 April 2017 17:39 Go to previous messageGo to next message
Finn Rayment is currently offline Finn RaymentFriend
Messages: 26
Registered: April 2017
Junior Member
Heres a quick picture of what I'm talking about:

index.php/fa/28971/0/

Where 'a' is a class in another file.

This is wrong because its acting as if its local, but its foreign. The error should be the other way around.

'C' is also foreign, but shown as local, and produces no errors. :/

[Updated on: Tue, 04 April 2017 17:41]

Report message to a moderator

Re: Limiting cross-reference to a single file [message #1758944 is a reply to message #1758943] Tue, 04 April 2017 17:52 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
i have a question,

why: namespace random.folders

but

second_file.ParentClass
use random.folders.second_file // also a FQN

?????

how does your name provider look like?



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

[Updated on: Tue, 04 April 2017 17:53]

Report message to a moderator

Re: Limiting cross-reference to a single file [message #1758976 is a reply to message #1758944] Wed, 05 April 2017 00:37 Go to previous messageGo to next message
Finn Rayment is currently offline Finn RaymentFriend
Messages: 26
Registered: April 2017
Junior Member
use random.folders.second_file


Refers to importing the file called "second_file" inside of the folder "random/folders".

Since "second_file" from folder "random/folders" has now been imported, you only have to reference things that come from it with "second_file".
Much like Java!

package random.folders
namespace random.folders

import random.folders.SecondFile
use random.folders.second_file

class Example extends SecondFile.ParentClass {}
class Example parent second_file.ParentClass {}


Of-course optionally, I'm also trying to be able to do this:

class Example extends random.folders.SecondFile.ParentClass {}
class Example parent random.folderssecond_file.ParentClass {}


It's a waste of time, but if we had two files say called 'Object', you want to be able to reference both of them.

You might also be a bit confused in the Java example, as to why there would be a class called SecondFile with a ParentClass in it.

In my language, the user only has to type

func RandomFunction: nil {}  // the filename is RandomFile


Which will be generated into Java as

class RandomFile {
        void RandomFunction {}
}


It's just because I want to "file-ify" the top-level class, so you can write methods at the top scope without first having to contain it in a class.

Thanks for your help Christian.

[Updated on: Wed, 05 April 2017 00:47]

Report message to a moderator

Re: Limiting cross-reference to a single file [message #1758979 is a reply to message #1758976] Wed, 05 April 2017 03:03 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
Hmmm that looks like you need a mixture of importuri and importnamespace based scoping. Unfortunately I don't have the time to create an example for that but I remember so year ago the same was asked and there was a solution

i can just give you a starting tipp. if you change grammar to

ImportDeclaration:
	'use' importURI=STRING
;


and add this binding

	override bindIGlobalScopeProvider() {
		ImportUriGlobalScopeProvider
	}


it works if you use imports like

use "platform:/resource/xxxxxx/random/folders/second_file.mydsl1"     // also a FQN

class ChildClass parent ParentClass {


if you adapt ImportUriResolver to turn your imports into the ones you want
then it will work for namespace imports as well.

additionally you need to adapt the nameprovider if you want to have the name "second_file.ParentClass"


public class StrangeNameProvider extends DefaultDeclarativeQualifiedNameProvider {
	
	QualifiedName qualifiedName(Model type) {
		return QualifiedName.create(type.eResource().getURI().trimFileExtension().lastSegment());
	}

}



	override bindIQualifiedNameProvider() {
		StrangeNameProvider
	}


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

[Updated on: Wed, 05 April 2017 03:44]

Report message to a moderator

Re: Limiting cross-reference to a single file [message #1758980 is a reply to message #1758979] Wed, 05 April 2017 03:36 Go to previous messageGo to next message
Finn Rayment is currently offline Finn RaymentFriend
Messages: 26
Registered: April 2017
Junior Member
Yea, I thought so....

Is there a way I can fix the cross-file referencing though? So the file limits its knowledge to itself?
Re: Limiting cross-reference to a single file [message #1758981 is a reply to message #1758980] Wed, 05 April 2017 03:45 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
see my update, that should be enhough to get started into the problem

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Limiting cross-reference to a single file [message #1758987 is a reply to message #1758981] Wed, 05 April 2017 05:23 Go to previous messageGo to next message
Finn Rayment is currently offline Finn RaymentFriend
Messages: 26
Registered: April 2017
Junior Member
I'm sorry for being a pain Christian and I appreciate your help.
I don't really know the ins-and-outs of Xtext at all, and just assumed that the bindIGlobalScopeProvider() binding belongs in the DSLScopeProvider.xtend file.

If this is the case, I've done what you said but really, nothing has happened. I don't really understand any of it either. Confused

[Updated on: Wed, 05 April 2017 05:28]

Report message to a moderator

Re: Limiting cross-reference to a single file [message #1758988 is a reply to message #1758987] Wed, 05 April 2017 05:38 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
how does your runtime module, your name provider, your grammar and your test model look like right now

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Limiting cross-reference to a single file [message #1759006 is a reply to message #1758988] Wed, 05 April 2017 08:17 Go to previous messageGo to next message
Finn Rayment is currently offline Finn RaymentFriend
Messages: 26
Registered: April 2017
Junior Member
Completely bare minimum.

I have absolutely NOTHING, but the .xtext model file along with the .mwe2 and generated files, and that DSLScopeProvider file which I basically stuck the method you gave me straight into it.
Re: Limiting cross-reference to a single file [message #1759007 is a reply to message #1759006] Wed, 05 April 2017 08:32 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
No, i mean:

please post your

-grammar
-MyDslRuntimeModule
-MyDslNameProvider
-Test model File

after applying my proposed changes


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Limiting cross-reference to a single file [message #1759012 is a reply to message #1759007] Wed, 05 April 2017 09:07 Go to previous messageGo to next message
Finn Rayment is currently offline Finn RaymentFriend
Messages: 26
Registered: April 2017
Junior Member
Sorry Christian.... Confused

Grammar:
grammar org.thusix.omicron.Omicron with org.eclipse.xtext.common.Terminals

generate omicron "http://www.thusix.org/omicron/Omicron"

Model:
	(
	package=PackageDeclaration
	imports+=ImportDeclaration*
	types+=Type*
	)?
;

PackageDeclaration:
	'namespace' name=FQN
;

ImportDeclaration:
	'use' importURI=FQN
;

TypeType:
	Primitive | TypeRef
;

TypeRef:
	ref=[Type | FQN]
;

Type:
	FunctionType | ClassType | EnumType
;

FunctionType:
	'func' name=ID ':' returnType=TypeType LBRACE
		fields+=Field*
	RBRACE
;

ClassType:
	'class' name=ID ('parent' superType=TypeRef)? ('inherits' templates+=TypeRef*)? LBRACE
		fields+=Field*
	RBRACE
;

EnumType:
	'enum' name=ID LBRACE
		values+=ID*
	RBRACE
;

Field:
	VariableDeclaration
;

VariableDeclaration:
	type=TypeType name=ID
;

/* Terminals and strings. */

Primitive:
	name=('int' |
	'long' |
	'short' |
	'float' |
	'double' |
	'str' |
	'char' |
	'bool' |
	'obj' |
	'byte' |
	'nil')
;

FQN:
	ID ('.' ID)*
;

terminal LBRACE: '{' ;
terminal RBRACE: '}' ;


DSLRuntimeModule:
/*
 * generated by Xtext 2.11.0
 */
package org.thusix.omicron


/**
 * Use this class to register components to be used at runtime / without the Equinox extension registry.
 */
class OmicronRuntimeModule extends AbstractOmicronRuntimeModule {
}


DSLScopeProvider that makes reference to the NameProvider
/*
 * generated by Xtext 2.11.0
 */
package org.thusix.omicron.scoping

/**
 * 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 OmicronScopeProvider extends AbstractOmicronScopeProvider {

	def bindIGlobalScopeProvider() {
		OmicronNameProvider
	}

}


DSLNameProvider which is custom and not stock:
package org.thusix.omicron.scoping

import org.eclipse.xtext.naming.DefaultDeclarativeQualifiedNameProvider
import org.eclipse.xtext.naming.QualifiedName
import org.thusix.omicron.omicron.Model

class OmicronNameProvider extends DefaultDeclarativeQualifiedNameProvider {
	
	def QualifiedName qualifiedName(Model type) {
		return QualifiedName.create(type.eResource().getURI().trimFileExtension().lastSegment());
	}
	
}


Test Model File:
namespace test

use test.Testing

enum Suite {
	Spades Hearts Diamonds Clubs
}

func t: a {
	
}

class Deck parent C {
	int i
}

class RedDeck parent test.Testing.a {
	
}
Re: Limiting cross-reference to a single file [message #1759013 is a reply to message #1759012] Wed, 05 April 2017 09:14 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
well you did not at all what i told you

class MyDslRuntimeModule extends AbstractMyDslRuntimeModule {
	
	override bindIGlobalScopeProvider() {
		ImportUriGlobalScopeProvider
	}
	
	override bindIQualifiedNameProvider() {
		StrangeNameProvider
	}


ImportDeclaration:
	'use' importURI=STRING
;


public class StrangeNameProvider extends DefaultDeclarativeQualifiedNameProvider {
	
	QualifiedName qualifiedName(Model type) {
		return QualifiedName.create(type.eResource().getURI().trimFileExtension().lastSegment());
	}

}


use "platform:/resource/xxxxxx/random/folders/second_file.mydsl1"     // also a FQN

class ChildClass parent ParentClass {


if this work then we can continue with the next step



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

[Updated on: Wed, 05 April 2017 09:16]

Report message to a moderator

Re: Limiting cross-reference to a single file [message #1759021 is a reply to message #1759013] Wed, 05 April 2017 11:26 Go to previous messageGo to next message
Finn Rayment is currently offline Finn RaymentFriend
Messages: 26
Registered: April 2017
Junior Member
Hey, I tried what you said before and as I previously wrote I didn't know where to put that override which you've clarified so I was able to fix it. Smile

I've done as you say and it works! Thankyou! The file will now throw an error because it can't find the specified type within itself!

The issue is though, those string imports are giving me errors. I'm assuming this is the next step Confused

index.php/fa/28978/0/
Re: Limiting cross-reference to a single file [message #1759022 is a reply to message #1759021] Wed, 05 April 2017 11:39 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
No,

you are still doing different things

the modell shall look like

use "platform:/resource/xxxxxx/random/folders/second_file.mydsl1"     // also a FQN

class ChildClass parent ParentClass {


or

use "platform:/resource/xxxxxx/random/folders/second_file.mydsl1"     // also a FQN

class ChildClass parent second_file.ParentClass {


yours does not.

this works fine on my machine.

if this works on your machine as well we can do the second step


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Limiting cross-reference to a single file [message #1759024 is a reply to message #1759022] Wed, 05 April 2017 11:54 Go to previous messageGo to next message
Finn Rayment is currently offline Finn RaymentFriend
Messages: 26
Registered: April 2017
Junior Member
Alright, here we go.
String encapsulation for import statement, normal qualified name for class.
Works beautifully. Thankyou very much.

index.php/fa/28980/0/

I'm more than happy having that error there, because I would like to use the file to reference which ParentClass I am talking about (Incase I have a local one too).
Re: Limiting cross-reference to a single file [message #1759026 is a reply to message #1759024] Wed, 05 April 2017 11:59 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
=> step one is fine for you? if yes

change grammar back to:

ImportDeclaration:
	'use' importURI=FQN
;


use this binding

	def Class<? extends ImportUriResolver> bindImportUriResolver() {
		StrangeImportUriResolver
	}


and implement the following class (just a stub so far that might not work in all cases)

public class StrangeImportUriResolver extends ImportUriResolver {
	
	@Inject
	FileExtensionProvider fileExtensionProvider;
	
	@Override
	public String apply(EObject from) {
		// TODO make more robust / potentially work in standlone mode if needed
		// or classpath:/my/pack/xxxx.mydsl if needed as well
		String apply = super.apply(from);
		if (apply == null) {
			return apply;
		}
		String result = "platform:/resource/" + from.eResource().getURI().segmentsList().get(1) + "/"
				+ apply.replaceAll("\\.", "/") + "." + fileExtensionProvider.getPrimaryFileExtension();
		System.out.println(result);
		return result;
	}

}


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Limiting cross-reference to a single file [message #1759033 is a reply to message #1759026] Wed, 05 April 2017 12:14 Go to previous message
Finn Rayment is currently offline Finn RaymentFriend
Messages: 26
Registered: April 2017
Junior Member
Beautiful! Thankyou VERY MUCH for your time, help and patience Christian! It works just as expected and I couldn't of asked for more! Shocked

My only question is: Is it possible to force the user to put the namespace of the class you want to use at the beginning?

Example, if we have the class "Testing.ParentClass" which the file has a namespace of "test", can we make them type "test.Testing.ParentClass"?

[Updated on: Wed, 05 April 2017 12:16]

Report message to a moderator

Previous Topic:Xtext multiple parameter to a method possibility
Next Topic:Scoping a feature call
Goto Forum:
  


Current Time: Thu Apr 25 07:09:42 GMT 2024

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

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

Back to the top