xtext: autoimport and -validate current package - xtext

I have two connected problems that I kind of know how to solve "by foot" (using custom validators and scope providers). But I'm surprised they don't work out of the box in xtext so I'll ask anyway (in case I missed something).
I have this DSL:
Model:
'package' name=QualifiedName
imports+=Import*
entities+=Entity*;
Import:
'import' importedNamespace=QualifiedName;
Entity:
name=ID '{'
references += Reference*
'}';
Reference:
name=ID':'entitiy=[Entity]
;
QualifiedName:
ID('.'ID)*
;
Apart from defining multiple entities in the same file I want to be able to define multiple files that "live" in the same package. And I have 2 problems here:
1) I found no obvious way to easily auto-import all elements from the current package. So If I have one file
package com.test
EntityA {}
and a second one
package com.test
import com.test.EntityA // fails if I remove this line
EntityB{
refToA:EntityA // I could make qualified names work here.
// But that is not the goal.
}
the reference to EntityA can't be resolved unless I explicitly import it (which is something that I want to avoid) although they are in the same namespace.
So: is there a way to easily enable outimports for the "current" package?
2) I have enabled the org.eclipse.xtext.validation.NamesAreUniqueValidator which works fine for entities defined in the same file. But if I redefine an imported entity like this
package com.test
import com.test.EntityA
EntityB{
refToA:EntityA
}
EntityA {}
I don't get the expected validation error. Is there something I can do about that without having to write my own validator?
Thx.

To make auto-imports work, you need to use Xbase and
Model:
'package' name=QualifiedName
importSection=XImportSection?
To use Xbase, append this to your grammar: with org.eclipse.xtext.xbase.Xbase
See http://www.lorenzobettini.it/2013/01/the_ximportsection_in_xbase_2_4/ for details.
The second one can only be solved with your own validator AFAIK. The reason is that you can have a grammar which allows:
import com.test.EntityA as X
private EntityA extends X {}

Related

What is the difference between these two packages importing ways in Dart language?

There are two ways to import packages in Dart programming language, I need to know what is the difference between them both, please?
Also when to use the first way and when to use the second way?
First way:
import 'dart:io';
Second way
import 'dart:io' as io;
as io specifies a prefix.
Without you can use members dart:io exports like
var f = File();
with prefix it would be
var f = io.File();
This is useful to disambiguate imports if names collide with declarations in your current library or another imported library.
Packages like path assume that they are imported with a prefix, because it exports many top-level functions with common names that without a prefix would clutter the scope.

Why do I get a "Could not resolve reference" when I use my XText grammar?

Here is my grammar:
grammar com.x.x.x.XxxDsl with org.eclipse.xtext.common.Terminals
generate xxxDsl "http://www.x.x.x.com/xxx/xtext/XxxDsl"
Root:
catalogs+=Catalog*
instances+=Instance*
;
Catalog returns Catalog:
'Catalog' name=ID
'{'
models+=Model*
'}'
;
Model returns Model:
'Model' name=ID
;
Instance returns Instance:
'Instance'
name=ID
'of'
model=[Model]
;
And here is my text:
Catalog myCatalog
{
Model meteo
Model storm
}
Instance wintermeteo of meteo
Instance strongstorm of storm
The 2 last lines are in error, meteo and storm being marked with:
Couldn't resolve reference to Model 'meteo'/'storm'
If I change my grammar so that the Models are directly in Root (and not inside Catalogs anymore) and update the text accordingly, then the models are correctly recognized.
What did I do wrong?
Xtext builds qualified names. So if your models have a parent with a name then the models name will be parentname.modelname
You can either adapt the IQualifiedNameProvider (subclass and bind DefaultDeclarativeQualifiedNameProvider or bind SimpleNameProvider) or you have to adapt the grammar to allow qualified names for the model reference
... model=[Model|FQN]
With
FQN: ID ("." ID)*;//pseudocode
As Christian has mentioned, cross-reference relies on the attribute "name" of the element (the instance created by the rule), to avoid problems due to duplicates, the default implementation of the name provider computes a qualified name, it concatenates the name of an element (Model) with the qualified name of its container (Catalog (Christian calls it parent)) recursively (root_name.catalog_name.model_name). The "name" of "meteo" is actually "myCatalog.meteo" (the rule Root has no "name="). If you don't want to adapt the IQualifiedNameProvider (to work only with simple names), you can adapt the grammar
... model=[Model|FQN]
...
FQN: ID ("." ID)*;
And now:
Catalog myCatalog
{
Model meteo
Model storm
}
Instance wintermeteo of myCatalog.meteo
Instance strongstorm of myCatalog.storm
should be accepted.

Namespace Conflict in swift with cocoa pod module

I have an enum in one of my Swift files called Foo.
One of the Cocoapods called NameA also has the same enum with name Foo (public enum, not inside any class).
This module also has a class with the same name as its framework NameA.
If I try to refer to Foo in NameA module like this:
NameA.Foo
It doesn't work because the compiler thinks I'm referring to the class NameA, but not the module NameA.
The workaround posted here wont work for me either Swift namespace conflict
This seems to be a reported bug in swift:
https://bugs.swift.org/browse/SR-898
Don't import NameA.
Instead, import enum NameA.Foo (notice the keyword "enum", can also be used for "struct" or "class" or "func")
Reference either Foo (your enum) or NameA.Foo (their enum).
If you need to reference NameA in the same file as NameA.Foo:
Create a new file for your "wrapper" type:
import NameA
typealias NameAWrapper = NameA
Reference the class NameA as NameAWrapper in your other files without importing the module directly.
This was inspired by this workaround (which you linked to), but modified slightly based on your situation: https://stackoverflow.com/a/26774102/358806
I ran into a similar issue recently. You won't like the solution I found, but I'll share it anyway. I had to fork the pod I was using and rename it to something new. The new project name no longer conflicted with the class name and I was able to namespace it as MyForkedName.ClassName. This is really an inconvenient way to do it, but in our case it was an older library that hadn't changed in some time (and one we will be removing altogether in the future) so I was willing to settle for now.
If you want to use enum from other module like Cocoapods or some framework you have to use this approach,
suppose I have enum Result defined in my project and same in some other module. You want to use both enum in same file then-
import enum MyFramework.Result
func doSomething(callback: (Result<Data>) -> Void) {
}
func doSomething1(callback: (MyFramework.Result<Data>) -> Void) {
}

Xtext Import with ScopeProvider

I have a grammar within Xtext that has a custom ScopeProvider, which extends AbstractDeclarativeScopeProvider. I am using this scope provider to accurately scope elements within the same DSL file.
It is simple to scope within the file, as one can simply traverse upwards/downwards through the model.
However, I'd now like to support imports from other classes. But I'm stuck how to find the elements in the other files from within my scope provider.
I can find instances of the import, which are specified in the grammar as:
Import:
"import" importURI=STRING
;
I can obtain the references to the import from the model, but this just contains the strings that are the URIs that reference the other files.
How to I get to the elements within the imported file?
hi i am not quite sure what your usecase is. the import statements simply makes the elements from the imported resources visible so that you can reference them
Model:
imports+=Import*
defines+=Define*
uses+=Use*
;
Import:
"import" importURI=STRING
;
Define:
"def" name=ID
;
Use:
"use" use=[Define]
;
with
a.mydsl
def a
b.mydsl
import "a.mydsl"
use a
i dont know why you explicitly want to search find it in the scopeprovider.
they are visible automatically
you may call
delegeteGetScope(ctx,ref)
in the scopeprovider to access the outer scope (the one from the imported files)
but what todo with it highly depends on your usecase

Two classes have the same xml type name

When I try to publish my Workspace in RAD, I get this error "Two classes have the same xml type name", probably because the same class name exists in the same package, but in two different jars. And it seems like that the #XmlType annotation needs to have distinct values for its attributes name and namespace in the sources of these classes. I tried wsdl2java available in Apache CXF, but I'm not able to make it generate this namespace attribute. I tried fiddling with the -p package option, but that's only for placing the generated sources in the specified package.
Any ideas how to generate this namespace attribute for each element encountered in the wsdl? TIA.
thanks to Daniel's anwser:
CXF JAXB JAXBEncoderDecoder unmarshalling error : unexpected element when having qualified elements
i learned there is a parameter -xjc-npa for wsdl2java which helped me.
This will add XmlType.name and XmlType.namespace annotations to the generated classes so it won't be a problem if you have same class names but in different namespaces
I ran into this for an object named "SubmitDataResponse" that I was using as a return object from my web service method named "submitData". When I tried renaming the object, the error went away. It seems to me that CXF is creating its own return object based on the method name (in this case submitData() -> "SubmitDataResponse"). You may want to try renaming the class and see if you are having the same issue. Perhaps someone can chime in with a way to keep our class named the way we want them to (probably with some annotation).
I hope this helps.

Resources