I'm currently playing with the Dart version of Angular 2.
I have seen that the library is using a lot of Metadata as #Component for example.
I would like to know how are those directives working?
I went on http://www.darlang.org. They explain how to define an annotation but not how to use it to construct an object as it is done in angular.io.
Could someone explain how the magic is working?
In Dart annotations by itself don't do anything than exist beside the code element where they are added.
At runtime:
You can use dart:mirrors to query the imported libraries for elements like fields, functions, classes, parameters, ... for these annotations.
dart:mirrors is discouraged for browser applications. In this case you can use the reflectable package with quite similar capabilities.
See also:
https://www.dartlang.org/articles/reflection-with-mirrors/
https://api.dartlang.org/1.14.1/dart-mirrors/dart-mirrors-library.html
https://stackoverflow.com/search?q=%5Bdart-mirrors%5D+annotations
At buildtime
You can create a transformer and register it in pubspec.yaml to be run by pub serve and pub build.
In this case the Dart analyzer can be utilized to query the source files for annotations and, like Angular does, modify the source code in a build step to add/replace/remove arbitrary code.
For more details about transformers
- https://www.dartlang.org/tools/pub/assets-and-transformers.html
- https://www.dartlang.org/tools/pub/transformers/
- https://www.dartlang.org/tools/pub/transformers/examples/
- https://www.dartlang.org/tools/pub/transformers/aggregate.html
- https://pub.dartlang.org/packages/code_transformers
Related
I would like to use objectbox inside a swift package, not inside a project, but on the documentation I couldn't find a procedure to follow to complete the operation.
I found no problem adding the library as a dependency:
.package(url: "https://github.com/objectbox/objectbox-swift", from: "1.8.0")
My problem is finding the correct strategy to use the code generator.
The documentation and scripts in the package say to call Sourcery like this:
"$sourcery" --xcode-project "${PROJECT_FILE_PATH}" --xcode-target "${TARGETNAME}" $MODULENAME1 $MODULENAME2 $#
In my case, the entities are present in my Package, so inside a directory, it would be correct if I use the Sourcery based ObjectBox code generator indicating the path "source" and the "output" instead of the project "--xcode-project " and of the "target"?
If this is not the correct way to go, do you have alternative ideas?
If an identifier is defined in the current dart file, then that identifier shadows elements with the same identifier that are defined in other files included using the import directive. When using such an identifier in the current file, no errors occur, the version from the current file is used.
If some id is defined in file 1 and file 2, but is not defined in the current file, then an error will occur when trying to apply the identifier, which can be eliminated by using import prefixes or show, hide commands.
The logic described above is clear. But when working with the dart:core library, the following error may occur. Let's consider the cause of the error using the print function as an example.
If the print function is not defined in the current file and that function is defined in one of the import files, then the dart:core version of the library will be grayed out. No compilation errors that require an import prefix or the show/hide command will be generated.
The described situation can lead to confusion. The same applies to some other dart:core libraries. There are examples below.
// test2.dart
void print() {
}
// test.dart
import 'test2.dart';
void main() {
// some useful function from test2.dart
print2();
// static error due to inappropriate argument types,
// not due to collision with print function from dart:core
print('work is done');
}
This error persists when explicitly including the dart:core file.
In connection with what has been said, there are the following questions.
Will the dart developers read my message, or where do they need to forward it to read it?
Is this really a bug or was it meant to be? I propose to correct it so that the language is more simple and understandable.
I expected that if an identifier in one of the files matches an identifier from the dart:core library, the behavior will be the same as if a simple other package, file.
The rules for name conflicts are special for names coming from platform (dart:) libraries.
Normally if you import different declarations with the same name through two different imports, it's a conflict. You get an error if you try to refer to the name, because the compiler cannot figure out which one you mean.
However, if you import different declarations with the same name, and some, but not all, come from dart: libraries, then the declarations from the dart: libraries are ignored, and the non-platform libraries take precedence. (And if there is only one declaration from a non-dart: library, it just works as normal.)
The reason for this exception is that Dart libraries typically come from packages, where you can control which version of the library you get.
You won't get new declarations without doing a dart pub update or similar. That means that a new name conflict are only introduced at times where you are actively developing, and you can then handle.
Platform libraries come from the SDK, and your SDK can be updated independently of the packages you are working on. Even if you tested your application thoroughly and locked all your dependencies to specific version that you know will work, it might end up being run on a newer SDK.
Because of that, adding new declarations to the platform libraries was considered more dangerous than adding them to normal packages. To avoid it being practically impossible to add anything to the platform libraries, it was instead decided to not make such new conflicts into errors.
If the platform libraries introduce a new declaration, it should not affect your imports. It won't introduce a new conflict.
(It can cause other errors, because no API change in Dart is ever entirely safe, but at least it won't cause import conflicts.)
Can someone tell me how to get protoc to generate dart files with a leading library directive?
I'm using the dart-protoc-plugin (v0.10.2) to generate my dart, c++, c#, js and java models from proto files. I was under the impression there was no way to get protoc to add a 'library' directive to the generated dart files, until I noticed the directive appearing in another project (see date.pb.dart).
If I take the same file (date.proto) I cannot get protoc to generate a dart file containing a 'library' directive.
In short: I want to take a .proto file with the following content
syntax = "proto3";
package another.proj.nspace;
message MyObj {
...
}
and produce a .dart file with a leading 'library' directive similar to the following snippet
///
// Generated code. Do not modify.
///
// ignore_for_file: non_constant_identifier_names,library_prefixes
library another.proj.nspace;
...
NOTE: I don't care about the actual value of the directive since I can restructure my code to get the desired result. I just need a way for protoc to add the library directive...
The basic command I'm using to generate the dart files is
protoc --proto_path=./ --dart_out="./" ./another/proj/nspace/date.proto
Unfortunately the dart-protoc-plugin's README isn't very helpful and I had to go through the source to find out which options are available; and currently it seems like the only dart-specific option is related to grpc.
I've tried options from the other languages (e.g. 'library', and 'basepath') without any success.
It would simplify my workflow quite a bit if this is possible, but I'm starting to get the impression that the library directive in date.pb.dart is added after the code was generated...
After asking around a little bit, it seems that the library directive was removed from the protoc plugin at some stage (see pull request), thus it is no longer supported.
I saw the following code snippet
val settings = configuration.underlying.as[CookieSecretSettings]("silhouette.oauth1TokenSecretProvider")
I believe configuration is of type play.api.Configuration and underlying is of typeConfig` (https://www.playframework.com/documentation/2.6.x/api/scala/index.html#play.api.Configuration)
I copied the code in my Apploader (as I am using Compile Time Injection). The BuiltInComponentsFromContext has a configuration variable. I thought to use that as follows val config = configuration.underlying.as[CookieAuthenticatorSettings]("silhouette.authenticator") but the compiler cannot resolve as. What am I doing wrong?
The Config library seem to have asInstanceOf instead of as but I get other errors if I use that. I notice that the code for which as works uses play version 2.4.2 while I am using 2.6.12.
I realize this is an old question, but I stumbled upon this exact problem today and couldn't find anything helpful.
The as method is provided by a third-party library (Ficus) to read case classes and Scala types from Typesafe config. You need to include it in your build dependencies, then add to imports:
import net.ceedubs.ficus.Ficus._
import net.ceedubs.ficus.readers.ArbitraryTypeReader._
Unlike inclusion of global.jsp with every component jsp in CQ5, sightly does not include any such dependency. How does it actually access all the global objects. What is the backend process of it. And how sightly code compiles to java??
how sightly code compiles to java?
Sling sightly API has two bundles to support this, the first step is to compile sightly into Abstract Syntax Tree (The Abstract Syntax Tree maps plain Java source code in a tree form. This tree is more convenient and reliable to analyse and modify programmatically than text-based source.) This is done by Apache Sling Scripting Sightly Compiler
Next is to convert (transpile) the Abstract Syntax Tree into java source code. This is achieved in bundle Java Compiler
How does it actually access all the global objects.
To understand this you need to understand how script resolution occurs in Sling and how are resource resolved to scripts which is core to Sling Scripting engine. To understand basics of ScriptEngine look at java docs here, implementation of this is SightlyScriptEngine
The way script resolution works is that the resource is adapted to DefaultSlingScript , this is done by SlingScriptAdapterFactory.
SlingScriptAdapterFactory has references to BindingsValuesProvider which is passed to the DefaultSlingScript. One of the implementation of BindingsValuesProvider is AEMSightlyBindingsValuesProvider (you can see this as a service in /system/console/services) which provides the default objects.
The DefaultSlingScript then responsible for invoking SightlyScriptEngine and calling its method eval which populates the default objects in binding and then setting this binding as request attribute.