How can advance google closure compilation be used with ES6 classes and arbitrary defineProperty? - google-closure-compiler

I maintain a data flow library that allows programmers to define new properties during instantiation, then does neat things at run-time with both property reads and writes, all transparently thanks to JS defineProperty. Sample usage, where TagSession is defined with the ES6 class keyword:
const sithApp = new TagSession( null, 'SithTrakSession',
{
obiTrakker: cF( c => new WebSocket('ws://localhost:4000')
.onmessage = msg => c.md.obiLoc = JSON.parse(msg.data)),
obiLoc: cI( null),
sithIds: cI([-1,-2,3616,-3,-4])
});
I can now write code where the map keywords are transparent accessors:
function SithTrak () {
return div({class: "app-container"},
h1({
class: "css-planet-monitor",
content: cF(c => "Obi-Wan currently on " +
(sithApp.obiLoc ?
sithApp.obiLoc.name : "...dunno"))
}))
}
This works great uncompiled and with Google Closure SIMPLE_OPTIMIZATION, but ADVANCED_COMPILATION warns (and the output fails) about, eg:
WARNING - Property obiLoc never defined on TagSession
withObi: cF( c=> c.md.info && sithApp.obiLoc
I have looked at all the annotations that might apply, but nothing seems suited to such a dynamic capability.
Am I missing something obvious, or is this combo of dynamism and optimization asking too much?

Dynamic properties added with this method would require using a bracket access for ADVANCED mode: sithApp['obiLoc']. In ADVANCED mode, the compiler must know about all properties accessed via the dot nation at compile time.

Since it isn't known that these properties are defined on the class you are going to get type warnings, bit it shouldn't break your code.
You can add declarations to silence the type warnings:
/** #type {?} */
TagSession.prototype.objLoc;
In other cases, you might be able to use #lends but I don't think this will work here as the types provided might not match the expected type of the property value. But there isn't enough context to be sure:
/** #lends {TagSession.prototype} */ ({
obiTrakker: ...,
obiLoc: ...,
sithIds: ...
})

Related

How do you implement a choice in a state machine in Qt?

Imagine a part of your state machine looks like this:
How do you properly implement the choice part in Qt? I know there are guarded transitions, but that would mean that I need to:
Create a subclass of a QAbstractTransition which accepts e.g. an std::function<bool()> and a flag which determines if the transition happens when that boolean result is true, or when it is false
Create two instances of this class with the same boolean function, but opposite transition guards
Add two transitions from S1 using these two instances.
That approach seems kind of clumsy and error prone for something as simple as a choice.
Is there a more maintainable approach to implement this?
License Notice:
Alternatively to the default StackOverflow license you are hereby allowed to use this code through the MIT License.
I've created a BooleanChoiceTransition class with a constructor like this (might contain errors, the code is not on this machine, so I typed it by heart):
BooleanChoiceTransition::BooleanChoiceTransition(std::function<bool()> choiceFunc, QState* targetForTrueCase, QState* targetForFalseCase)
: QState{}
{
this->addTransition(this, &BooleanChoiceTransition::transitionToTrueTarget, targetForTrueCase);
this->addTransition(this, &BooleanChoiceTransition::transitionToFalseTarget, targetForFalseCase);
(void)QObject::connect(this, &QAbstractState::entered, [this]() {
if(choiceFunc())
{
emit transitionToTrueTarget();
}
else
{
emit transitionToFalseTarget();
}
});
}
with transitionToTrueTarget and transitionToFalseTarget being signals of course.
For the case of the example in the question, the class can be used like so:
auto choiceState = new BooleanChoiceTransition([this](){ return _someConditionFullfilled; }, s2, s3);
s1->addTransition(this, &MyClass::someTrigger, choiceState);
Since BooleanChoiceTransition is a QState, this can even be nested easily:
auto outerChoiceState = new BooleanChoiceTransition([this](){ return _someOtherConditionFullfilled; }, s4, choiceState);

Dart - Casting List<SuperType> to List<SubType> using generics

I am new to Flutter and Dart, coming from native Android.
Android has a very nice database abstraction architecture called the Room Persistence Library. As far as I am aware, no such database abstraction architecture exists for Flutter using the MVVM / MVC design patterns.
My solution was to create a Dart version of it myself. I got it pretty much done after a few headaches, but I cannot seem to get LiveData to work properly using generics.
I set up my class like this:
class LiveData<T> {
...
}
Now when I want to return some data, it can either be an Object or List<Object>. I found a neat hack for differentiating the two from T:
...
// Parse response
// This checks if the type is an instance of a single entity or a list.
if (entity is T) {
cachedData = rawData.isEmpty ? null : entity.fromMap(rawData.first) as T;
} else {
cachedData = rawData.map((e) => entity.fromMap(e)).toList() as T;
}
...
The problem lies in the second block:
cachedData = rawData.map((e) => entity.fromMap(e)).toList() as T;
With the error:
- Unhandled Exception: type 'List<Entity>' is not a subtype of type 'List<Vehicle>' in type cast
The question then becomes: How can I cast Entity to Vehicle when I do not have access to the Vehicle class. Only an instance of it is assigned to an Entity entity variable.
Here's a snippet to demonstrate my access to Vehicle:
final Entity entity;
...assign Vehicle instance to entity...
print(entity is Vehicle) // True
I've tried using .runtimeType to no avail. I have also thought about splitting LiveData into two classes, the second one being LiveDataList. Although this seems to be the easiest solution to not bug the code- it would bug me (bad pun is intentional) and break the otherwise pretty direct port of Room.
As a temporary solution, I have abstracted out the build logic into a generic function to be passed to the LiveData in the constructor.
final T Function(List<Map<String, dynamic>> rawData) builder;
And now I call that instead of the previous code to build the cachedData.
// Parse response
cachedData = builder(rawData);
With the constructor for the LiveData<List<Vehicle>> called when accessing all vehicles in the Dao<Vehicle> being:
class VehicleDao implements Dao<Vehicle> {
...
static LiveData<List<Vehicle>> get() {
return LiveData<List<Vehicle>>(
...
(rawData) => rawData.map((e) => Vehicle.fromMap(e)).toList(),
...
);
}
}
In Dart (and indeed in many languages) generics screws with the concept of inheritance. You would think that if Bar inherits from Foo, that List<Bar> would also be castable to List<Foo>.
This is not actually going to be the case because of how generics work. When you have a generic class, every time you use that class with a different type, that type is treated as a completely separate class. This is because when the compiler compiles those types, class MyGenericType<Foo> extends BaseClass and class MyGenericType<Bar> extends BaseClass are basically converted to something like class MyGenericType_Foo extends BaseClass and class MyGenericType_Bar extends BaseClass.
Do you see the problem? MyGenericType_Foo and MyGenericType_Bar are not descendants of one another. They are siblings of each other, both extending from BaseClass. This is why when you try to convert a List<Entity> to List<Vehicle>, the cast doesn't work because they are sibling types, not a supertype and subtype.
With all this being said, while you cannot directly cast one generic type to another based on the relationship of the generic type parameter, in the case of List there is a way to convert one List type to another: the cast method.
List<Entity> entityList = <Entity>[...];
List<Vehicle> vehicleList = entityList.cast<Vehicle>(); // This cast will work
One thing to note though, if you are casting from a supertype generic to a sub-type generic and not all the elements of the list are that new type, this cast will throw an error.

Kotlin Reflection - Check if property has type

I want to iterate over all fields in one of my classes, filter for annotated ones and then check if the field has one specific type.
All I found was field.returnType.isSubtype(other: KType) but I don't know how to get the KType of my other class.
Here is my code so far:
target.declaredMemberProperties.forEach {
if (it.findAnnotation<FromOwner>() != null) {
if ( /* it.returnType is Component <- Here I need some working check */ ) {
// do stuff
} else {
// do ther stuff
}
}
}
There are at least two solutions here:
Get the KClass<*> of it.returnType using .jvmErasure, then check the subtype relationship for the KClasses:
it.returnType.jvmErasure.isSubclassOf(Component::class)
Since Kotlin 1.1, you can construct the KType from the KClass token using .createType() (check its optional parameters: you can use them to provide nullability info, type arguments and annotations), and then check the subtype as you suggested:
it.returnType.isSubtypeOf(Component::class.createType())
Creating the type on every iteration may introduce performance issues, make sure you cache it if you need it often.

Typescript reflection - required parameters & default values

In short: is there a way to know if a typescript parameter is required and/or has a default value?
Longer version:
Say I have the following file:
//Foo.ts
class Bar {
foo(required:string,defaultValue:number=0,optional?:boolean) {
...
}
}
I would like to know of each of the parameters:
the name
the type
is it required?
does it have a default value?
I have succesfully used method decorators with the TypeScript reflection API to get the types of the parameters, I've used this method to get their names, but so far I have not found a way to know if a variable is required and/or has a default value.
I know the typescript compiler itself can be used from within typescript. So I'm wondering if there is a way to use the parse tree of the compiler to see if a parameter is required and/or has a default value?
How would that work?
If you want to do this from scratch...
On a high level, one way of doing it is to:
Figure out how to get the SourceFile node using the compiler api of your file. That requires a bit of an explanation in itself.
From there, use the api's forEachChild function to loop over all the nodes in the file and find the node with a kind of SyntaxKind.ClassDeclaration and .name property with text Bar.
Then loop over all the children of the class by again using the api's forEachChild function and get the ones that has the kind SyntaxKind.MethodDeclaration and .name property with text foo.
To get the parameters, you will need to loop over the method node's parameters property.
Then for each parameter node, to get the name you can call .getText() on the .name property.
You can tell if the parameter is optional by doing:
const parameterDeclaration = parameterNode as ts.ParameterDeclaration;
const isOptional = parameterDeclaration.questionToken != null || parameterDeclaration.initializer != null || parameterDeclaration.dotDotDotToken != null;
Or you could use the TypeChecker's isOptionalParameter method.
To get its default expression, you will just have to check the initializer property:
propertyDeclaration.initializer;
To get the type use the TypeChecker's getTypeOfSymbolAtLocation method and pass in the symbol of the node... that gets a little bit complicated so I won't bother explaining it (think about how it's different with union types and such).
Don't do it from scratch...
I've created a wrapper around the TypeScript compiler api. Just use this code with ts-simple-ast (edit: Previously this talked about my old ts-type-info library, but ts-simple-ast is much better):
import { Project } from "ts-morph";
// read more about setup here:
// https://ts-morph.com/setup/adding-source-files
const project = new Project({ tsConfigFilePath: "tsconfig.json" });
const sourceFile = project.getSourceFileOrThrow("src/Foo.ts");
const method = sourceFile.getClassOrThrow("Bar").getInstanceMethodOrThrow("foo");
Once you have the method, it's very straightforward to get all the information you need from its parameters:
console.log(method.getName()); // foo
for (const param of method.getParameters()) {
console.log(param.getName());
console.log(param.getType().getText());
console.log(param.isOptional());
console.log(param.getInitializer() != null);
}

using export in alloy controller versus attaching functions directly to the '$' scope

here is the code of an alloy controller written in two different ways. Although the both work the same, Which one might be best practice?
example 1 of controller.js:
var currentState = true;
$.getState = function(){
return currentState;
}
example 2 of controller.js:
var currentState = true;
exports.getState = function(){
return currentState;
}
Titanium is based on the CommonJS framework. The exports variable is a special variable used typically to expose a public API in a class object. So when you want to expose a method of doSomething() on the MyModule.js class you would use the exports variable like this:
exports.doSomething() = function(args) {
//Some really cool method here
};
Then reference that class using
var myModule = require('MyModule');
myModule.doSomething();
However when referencing a view object the typical way to reference the is using the $. shortcut. You can see they prefer that method in the official documentation.
http://docs.appcelerator.com/platform/latest/#!/guide/Alloy_XML_Markup
The $ variable holds a reference to your controller instance. It also contains some references to all indexed views (understand, views for which you supplied an index in you xml markup).
Both ways are strictly equivalent as, during the compilation, Alloy will merge the content of the exports with your controller referenced in $. Adding them directly to the instance won't change a thing.
Neverthless, developers are used to see the public API as the set of functions exported via the special variable exports; Thus, I will recommend to keep using it in a clean and clear way (for instance, defining your functions in your module scope, and only expose them at the end or beginning of your controller).
function myFunction1 () { }
function myFunction2 () { }
function myFunction3 () { }
exports.myFunction1 = myFunction1;
exports.myFunction3 = myFunction3;
Thereby, your API is quite clear for people diving into your source code. (A readMe file is also highly recommended :) ).

Resources