Limiting cross-reference to a single file [message #1758920] |
Tue, 04 April 2017 15:30 |
Finn Rayment 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.
[Updated on: Tue, 04 April 2017 15:31] Report message to a moderator
|
|
|
|
|
|
|
|
Re: Limiting cross-reference to a single file [message #1758941 is a reply to message #1758936] |
Tue, 04 April 2017 17:30 |
Finn Rayment 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 #1758976 is a reply to message #1758944] |
Wed, 05 April 2017 00:37 |
Finn Rayment 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 |
|
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
Day Job: https://www.everest-systems.com
[Updated on: Wed, 05 April 2017 03:44] Report message to a moderator
|
|
|
|
|
|
|
|
|
|
Re: Limiting cross-reference to a single file [message #1759013 is a reply to message #1759012] |
Wed, 05 April 2017 09:14 |
|
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
Day Job: https://www.everest-systems.com
[Updated on: Wed, 05 April 2017 09:16] Report message to a moderator
|
|
|
|
|
|
Re: Limiting cross-reference to a single file [message #1759026 is a reply to message #1759024] |
Wed, 05 April 2017 11:59 |
|
=> 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
Day Job: https://www.everest-systems.com
|
|
|
Re: Limiting cross-reference to a single file [message #1759033 is a reply to message #1759026] |
Wed, 05 April 2017 12:14 |
Finn Rayment 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!
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
|
|
|
Powered by
FUDForum. Page generated in 0.04985 seconds