Xtext Import with ScopeProvider - xtext

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

Related

How to avoid writing an import for every single file in dart/flutter?

I am making a flutter application and I created a file/class for each custom widget I am using. Then, I imported all of these files into the main screen but I don't like how it looks. Especially because if I want to add another widget or delete the one I would need to fiddle with the imports.
Is there something like C# namespaces where I can just make one import for all files in folder/namespace?
I already tried using library/part with success but then in https://www.dartlang.org/guides/libraries/create-library-packages says that I should avoid using part/part of. So, are we expected to import each and every file?
Instead of having:
import 'package:custom_widgets/custom_multiplechoice.dart';
import 'package:custom_widgets/custom_singlechoice.dart';
import 'package:custom_widgets/custom_time.dart';
import 'package:custom_widgets/custom_yesnochoice.dart';
import 'package:custom_widgets/custom_date.dart';
I would like to have:
import 'package:custom_widgets';
Yes there is, you can use export to achieve what you want.
You can place all your widgets in a folder, for example libs/src/ and then create file custom_widgets.dart in libs/ and use export like this inside custom_widgets.dart:
export 'src/custom_multiplechoice.dart';
export 'src/custom_singlechoice.dart';
export 'src/custom_time.dart';
export 'src/custom_widgets/src/custom_yesnochoice.dart';
export 'src/custom_date.dart';
Once you import custom_widgets.dart, all those widgets will be available to you.
Check this out, its all explained here: Dart: Organizing a library package
Update:
In Dart there are no namespaces like in most other languages.
Dart uses libraries for encapsulation, data hiding.
Only way to import a class into your code is to use import in the beginning of your file, which should also be a library.
I have an issue with this too. Imagine a situation where you want to import library dynamically. Let's say you would like to implement MVC pattern in your application, if you are doing this on the server, you would have a Router class that would analyze URL and decide what Controller class to instantiate and what Method from that Controller to invoke. Now every URL would trigger different Controller, and you don't know it in advance, its up to your Router to detect a Class to instantiate. What you need to do in this situation is import every Controller that could get instantiated at the beginning of your file. And I have issues with that. What if your application gets big and you have to import lets say 20 Controller classes, just so Router / Dispatcher can invoke one of them, and in reality you will invoke only one Controller, as there is only Controller per URL.
Don't have issues with manual loading of Libraries, if they are going to be used, but for situation like described above, Dart fails as there is no "auto loading" of classes like in for example PHP, where you can use auto loaders that use namespaces to find out about location of your class and instantiate a class in the middle of the code dynamically.
There is this extension for VSCode which can help to create this.
Dart Barrel File Generator

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.

xtext: autoimport and -validate current package

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 {}

Why Is the "library" line needed for Dart?

For a library file (say foo.dart), you start it with a line like this:
library my_foo_lib;
Why is it needed? The import is based on file name (foo.dart), not library string (my_foo_lib):
import 'package:foo.dart';
Having to declare library seems redundant and error-prone. Is there a good reason behind it?
You can omit the library statement then it is an implicitly named library with an empty string as name but when you import a library you need to name it explicitly otherwise you get an error that you have several libraries with the same name.
Identifiers starting with an _ (underline) are private. Privacy in Dart is per library.
The part of references the library name.
When you use reflection to look up classes or functions you include the library name. This way you can differentiate classes with the same name in different libraries.
Dart Programming Language Specification (17 Libraries and Scripts) also says
"The name may be relevant for further language evolution."

Warning that 'imported libraries have the same name when they DO NOT"

I have the following import statements in a class
import 'package:dart_web_toolkit/ui.dart';
import '../../util/flex_table_builder.dart' as ftBldr;
import '../factors_list_view.dart';
class MediatingFactorsView extends Composite
{
//...
}
However, the last import statment is flagged with a warning:
The different imported libraries 'flex_table_builder.dart' and 'factors_list_view.dart' should not have the same name
The names are quite different and I see this being repeated throughout my code after I updated to the latest Dart Editor. Is this a bug?
Make sure that you are assigning library names to each file. The first line of the file should be:
library foo;
You should use different names for each library that you use. The library name is specified by the library directive, but anonymous libraries are treated as having the same name, which is where the warning comes from.
It is a warning in the Dart specification to import two libraries with the same name.
You can read more about how to use libraries here in the language tour.
You could follow the Package layout conventions.
For the error :
The different imported libraries onset_view.dart and duration_view.dart should not have the same name
you should define distinct library names in each imported dart file.
One additionnal note, you should use import 'package:epimss/shared.dart'; instead of import 'packages/epimss/shared.dart'; and import 'site_view.dart'; instead of import './site_view.dart';
The warnings correctly indicate there is a problem.
The correct solution depends on if the Dart files are conceptually separate from each other or are related.
Different libraries
If they are conceptually separate, then they should be defined as belong to different libraries with different library names.
The import command is used to reference a compilation unit from a different library, not a compilation unit that belongs to the same library. It expects every library to have a unique library name.
If a Dart file is treated as a library (i.e. is the subject of an import statement) and is not explicitly named then its implicit name is the empty string. In this case, both files are treated as libraries, and it is complaining about there being two libraries with the same name (of an empty string).
For this to work as separate libraries, given them different names:
Top file:
import 'foo.dart';
import 'bar.dart';
foo.dart:
library foo;
bar.dart:
library bar;
Part of the same library
But if they related they should not be referenced as libraries. That is, do not use the import command. Use the part command, which treats the Dart file as compilation unit that belongs to the same library.
Top file:
library baz;
part 'foo.dart';
part 'bar.dart';
foo.dart:
part of baz;
bar.dart:
part of baz;
Only the top library file can contain the part statements. You do not need (and cannot have) part statements inside the other files, even if they reference definitions from each other. If there are multiple files, just list them all in the top library file (in any order).
Although the implicit name for a library is the empty string, there is no way to use that when there are multiple parts involved: so even if these files are never going to be imported as a library, you will still need to explicitly assign it a library name.
Always remember: import and part statements are very different from the #include macro in the C preprocessor.

Resources