how can I write an annotation for Dart - javascript

The question:
What is the procedure to implement an annotation.
How can, or indeed when can one activate the annotation you developed?
I can't seem to find an example or tutorial on how to write a class to implement annotations for dart.
For example with Java you might have an annotation that represents a class that is invoked at compile time and let you modify or inject code. Do Dart annotations work like this as well?
background
I have done some (further) digging on understanding this area of the Dart ecosystem. I'm adding some notes because annotation can be a powerful with transparent commentary on how to use it.
After looking at some actual annotation from Dart, Dart annotations record "a notation" (a label or metadata tags). The question is about how to uses annotations within Dart.
gloaming
My current understanding, based on looking at bits of code, is that they are markers on class objects. It looks like annotations are highly-unstructured since while an annotation can be declared simply, there's no structure to use or recognise a label (aka annotation).
steps of annotation
Identify the property or action you want to label.
Need to write code to use or 'work' your annotation. Look at something like Observe as an example.
You can implement and test LOAD-time code to look-for and process your labels. I don't see an infrastructure to register an annotation and provide handlers for example.
This is done via the main() method in your library.
Implement and test annotation behaviour.
At least I think that's how it works. There's not really a lot of information in the Dart language specification on this area.
Observation and inspection raised a few general questions as well. I've left a reading list of sorts and examples, to assist others in joining the exploration.
readings:
Dart Language Specification
type annotations
metadata
extending a class
I love Dart annotations
zones
zone class
Dart Annotations are No Longer Structured
examples:
Observe
Observable.dart
annotations.dart

Any class with a const constructor can be used as annotation.
const FOO = const Foo(37);
#Foo(42)
class Foo {
#Deprecated("until further notice");
final int x;
#FOO
const Foo(this.x);
}
There is nothing more to it.
See also https://www.dartlang.org/docs/dart-up-and-running/contents/ch02.html#ch02-metadata
Metadata doesn't do anything by itself. If your program wants to read metadata off a class, it needs to use mirrors.
import 'dart:mirrors';
const tag = "TAG";
#tag class C {}
void main() {
print(reflectClass(C).metadata.first.reflectee); // prints "TAG"
var c = new C();
print(reflect(c).type.metadata.first.reflectee); // prints "TAG"
}
See: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart-mirrors.ClassMirror#id_metadata
Alternatively, you can process the source directly. For example, the dart2js compiler has a "source mirror" library that reflects over the source structure. It is what dart2js and the analyzer do to understand the "proxy" annotation.

Related

Is there any way to access existing visual studio type data or vscode extension outputs?

I'm currently trying to write my own VSCode extension.
The purpose of this extension is to compare types of HTML Custom Attributes and javascript code expressions.
Now, it's completely possible to get the type of HTML attributes, there are NPM packages and as long as they're documented via JSDoc or have proper types using typescript - no problem.
but now look at the following example:
/** #param {MyPage} page */
export function renderSomePage(page)
{
return html`
<my-component .my-attribute="${page.SomeProperty}"></my-attribute>
`
}
the question now is, how do I get the type of the expression ${page.SomeProperty}? This is the main question i want to solve with this question.
I have some ideas.
visual studio does already know what type this expression is. Because when i hover over the parts of this expression, then i get a hover showing me the type. So ideally i want to receive some kind of Dictionary of tokens mapped to types that VSCode must have somewhere
there's always the typescript/javascript language support plugin in VSCode that probably does all that work for the IDE. I'd need to get exactly those compiling/parsing results to get to the type of this expression
of course there are also corner cases, where it's not that simple. I also need to be able to evaluate expressions like:
(args) => result
identfiier.function()
primitive types (string, number, boolean)
arrays of complex types
anonymous objects
arrays of anonymous objects
You didn't mention anything about an LSP, which tells me that that is what your missing.
Bellow is in reference to idea #1 in the question:
The type information that you see when hovering is generated by the "TS LSP", which stands for...
"TypeScript Language Server Provider"
What you want to do is use a feature called "Request Forwarding" to access the information already present, which is provided by the VSCode LSP.
I believe that the node Language server provides features for TypeScript, and always runs in the background. This is because VSCode runs in a Node RTE, and it has built-in features that are written in TypeScript. If you were writing a language like Go (or Go) per-say, then you would need to call to that specific language server.
You can use the "VS Code Language API", which makes requests to language servers. The API is written to work with language server that adheres wholey to the "Language Server Protocol". to access the "Programmatic LSP Features".
VSCode has a few examples that demonstrate how to use the LSP.
Really, you have two options, you can...
...parse TypeScript yourself, write grammars for the embedded mark-up, pull out all the type info, and write the type checking software you intend to write, or you can...
...use the already existing LSP to access the info, which includes requests for type info, and then write the type-checking software.
Hopefully that points you in the write direction.

Generate object from Typescript interface

I realize this is essentially the opposite intent of Typescript, but I would like to be able to programmatically generate an object FROM a typescript interface. Basically, I want something like this:
interface Foo {
bar: string
}
const generateObjFromInterface = (Foo) => // { bar: 'string'}
I -do not- mind how contrived the implementation is if it IS possible! If it is categorically impossible that would also be helpful information!
Thanks in advance!
It is possible. As typescript 2.4 is around the corner we can use custom transformers for typescript during compilation and get the list of all properties that are there and as a result create object with such properties.
Here is an example, but please note - as I have said this require to use typescript 2.4+ that is not yet in stable release
Since TypeScript's interfaces are not present in the JavaScript output, runtime reflection over an interface is impossible.
Given this TypeScript:
interface Foo {
bar: string
}
This is the resultant JavaScript:
Since there is no JavaScript, what you want to do is categorically impossible is very contrived.
Edit: Come to think of it, you could find, read, and parse the *.ts source file at runtime.
I also was searching for something that could do it and I didn't find anything. So I build this lib https://www.npmjs.com/package/class-validator-mocker, which can generate random data for classes attributes annotated with class-validator's decorators. Worked pretty well for my purposes.
I did it by using intermock (Google)
Here is a demo page

qx.log.appender Syntax

When declaring qx.log.appender.Native or qx.log.appender.Console, my IDE (PyCharm) complains about the syntax:
// Enable logging in debug variant
if (qx.core.Environment.get("qx.debug"))
{
qx.log.appender.Native;
qx.log.appender.Console;
}
(as documented here)
The warning I get is
Expression statement is not assignment or call
Is this preprocessor magic or a feature of JavaScript syntax I'm not aware yet?
Clarification as my question is ambiguous:
I know that this is perfectly fine JavaScript syntax. From the comments I conclude that here's no magic JS behavior that causes the log appenders to be attached, but rather some preprocessor feature?!
But how does this work? Is it an hardcoded handling or is this syntax available for all classes which follow a specific convention?
The hints how to turn off linter warnings are useful, but I rather wanted to know how this "magic" works
Although what's there by default is legal code, I find it to be somewhat ugly since it's a "useless statement" (result is ignored), aside from the fact that my editor complains about it too. In my code I always change it to something like this:
var appender;
appender = qx.log.appender.Native;
appender = qx.log.appender.Console;
Derrell
The generator reads your code to determine what classes are required by your application, so that it can produce an optimised application with only the minimum classes.
Those two lines are valid Javascript syntax, and exist in order to create a reference to the two classes so that the generator knows to include them - without them, you wouldn't have any logging in your application.
Another way to create the references is to use the #use compiler hint in a class comment, eg:
/**
* #use(qx.log.appender.Native)
* #use(qx.log.appender.Console)
*/
qx.Class.define("mypackage.Application", {
extend: qx.application.Standalone,
members: {
main: function() {
this.base(arguments);
this.debug("Hello world");
}
}
});
This works just as well and there is no unusual syntax - however, in this version your app will always refer to the those log appenders, whereas in the skeleton you are using the references to qx.log.appender.Native/Console were surrounded by if (qx.core.Environment.get("qx.debug")) {...} which means that in the non-debug, ./generate.py build version of your app the log appenders would normally be excluded.
Whether you think this is a good thing or not is up to you - personally, these days I ship all applications with the log appenders enabled and working so that if someone has a problem I can look at the logs (you can write your own appender that sends the logs to the server, or just remote control the user's computer)
EDIT: One other detail is that when a class is created, it can have a defer function that does extra initialisation - in this case, the generator detects qx.log.appender.Console is needed so it makes sure the class is loaded; the class' defer method then adds itself as an appender to the Qooxdoo logging system
This is a valid JS syntax, so most likely it's linter's/preprocessor's warning (looks like something similar to ESLint's no-unused-expressions).
Edit:
For the other part of the question - this syntax most likely uses getters or (rather unlikely as it is a new feature) Proxies. MDN provides simple examples of how this works under the hood.
Btw: there is no such thing as "native" JS preprocessor. There are compilers like Babel or TypeScript's compiler, but they are separate projects, not related to the vanilla JavaScript.

Include JavaScript and HTML files in class diagram?

My current application uses a JavaFX Application class with gui code (including a webview) and regular Java classes. This webview shows a html file which has JavaScript files as reference. My JavaScript has access to one of my classes like so:
private JSONModel model = new JSONModel();
JSObject jsobj = (JSObject) webEngine.executeScript("window");
jsobj.setMember("java", model);
Meaning my d3.js has full access to call methods of my JSONModel.class. Since it is that important to the project, should I include it in my class diagram? How would I make clear that it is JavaScript and not a Java class?
Whether or not you include something in your class diagram depends on the purpose of this diagram.
If you think it's important to put it on there then I guess you should.
More or less the same applies for the difference between Java Class and JavaScript class; it all depends on the purpose and audience.
If the purpose of the diagram is to show the structure to a business analyst then you should not show the difference (it will only confuse the poor guy and will not help to get the message across).
If the purpose of the diagram is to instruct developers what to build, then you should somehow make the difference clear.
How you do this depends on your modeling method and tool. Some tools allow to set the language of the class.
From a pure UML standpoint I think you should work with something like a Manifestation to indicate that you implement a certain class in a certain artifact.
From UML 2.5 specs:
The manifestation relation can be between an artifact, and any PackageableElement
All important classes should be covered, especially when the required level of detail is low-level.
You can use <<stereotype>> to distinguish between JavaScript and Java classes as shown in uml-diagrams.org: Submit Comments to Pluck, UML Sequence Diagram Example
[]1

Flow type annotations and valid JavaScript source

I'm playing with Facebook's new Flow Type checking system.
In Flow, meet Underscore it appears that they change this JavaScript code
var root = this;
into this
var root: any = this;
But this is no longer valid JavaScript, right? I understand why external Interface files would be useful, but how are type annotations added directly into valid JavaScript sources?
Previously, Google Closure compiler and other projects used on JS comments.
As of Flow 0.4.0 you are able to put the Flow syntax into the comments. This solves your issue. So your example would look like:
var root/*: any*/ = this;
This results in valid JavaScript syntax and there is no need to transpile your code.
Further details can be found here:
http://flowtype.org/blog/2015/02/20/Flow-Comments.html
You're right, that code is no longer valid javascript. That means that when you use Flow in someJavascriptFile.js, you have to execute a program that removes the Flow code from someJavascriptFile.js, which is called transpiling. Which transpiler to use depends on how you're running javascript, and will probably change over time, so I won't link to any.
You can also wrap the flow types into a comment, eg. var name /*:string*/ = "Hello flow.", which is valid javascript, but makes the code harder to read in my opinion.
In theory, Javascript engines could one day natively support Flow parsing, but that's a long ways off.
I missed Running Flow code where it discusses adding a build step to remove type annotations.
You can use the JSX transform tool (part of the React tools) to
translate your files to plain JavaScript
I also found flow-typestrip which is alternative.
I like external interface files per module better, as you can avoid introducing a build step.

Categories

Resources