Make setter bypass in constructor optional.
This commit is contained in:
@@ -320,7 +320,7 @@ class Constructor {
|
|||||||
function publish():Void;
|
function publish():Void;
|
||||||
function addStatement(e:Expr, ?prepend = false):Void;
|
function addStatement(e:Expr, ?prepend = false):Void;
|
||||||
function addArg(name:String, ?t:ComplexType, ?e:Expr, ?opt = false)
|
function addArg(name:String, ?t:ComplexType, ?e:Expr, ?opt = false)
|
||||||
function init(name:String, pos:Position, with:FieldInit, ?prepend:Bool):Void;
|
function init(name:String, pos:Position, with:FieldInit, ?options:{ ?prepend:Bool, ?bypass:Bool }):Void;
|
||||||
function onGenerate(hook:Expr->Expr):Void;
|
function onGenerate(hook:Expr->Expr):Void;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -347,16 +347,14 @@ To add a constructor argument, you can just use `addArg`.
|
|||||||
|
|
||||||
### Field initialization
|
### Field initialization
|
||||||
|
|
||||||
The `init` method is the swiss army knife of initializing fields. The `prepend` parameter works the same as for `addStatement`. As for the rest, the behavior is somewhat magical.
|
The `init` method is the swiss army knife of initializing fields. The `options.prepend` flag works the same as `prepend` for `addStatement`. As for `options.bypass`, the behavior is somewhat magical.
|
||||||
|
|
||||||
#### Setter bypass
|
#### Setter bypass
|
||||||
|
|
||||||
It is important to know that when you initialize a field this way, existing setters will by bypassed. That's particularly helpful if your setter triggers a side effect that you don't want triggered. This is achieved by generating the assignment as `(untyped this).$name = $value`. To make the code typesafe again, this is prefixed with `if (false) { var __tmp = this.$name; __tmp = $value; }`. This code is later thrown out by the compiler. Its role is to ensure type safety without interfering with the normal typing order.
|
It is important to know that when you initialize a field with `options.bypass` set to true, existing setters will by bypassed. That's particularly helpful if your setter triggers a side effect that you don't want triggered. This is achieved by generating the assignment as `(untyped this).$name = $value`. To make the code typesafe again, this is prefixed with `if (false) { var __tmp = this.$name; __tmp = $value; }`. This code is later thrown out by the compiler. Its role is to ensure type safety without interfering with the normal typing order.
|
||||||
|
|
||||||
Please do note, that the value will be in the generated code twice, therefore if it is an expression that calls a macro, the macro will be called twice.
|
Please do note, that the value will be in the generated code twice, therefore if it is an expression that calls a macro, the macro will be called twice.
|
||||||
|
|
||||||
If you want to call the setter or avoid these tricks then use `addStatement` instead.
|
|
||||||
|
|
||||||
#### Initialization options
|
#### Initialization options
|
||||||
|
|
||||||
The different options for initialization are as follows:
|
The different options for initialization are as follows:
|
||||||
|
|||||||
@@ -66,7 +66,9 @@ class Constructor {
|
|||||||
public function addArg(name:String, ?t:ComplexType, ?e:Expr, ?opt = false)
|
public function addArg(name:String, ?t:ComplexType, ?e:Expr, ?opt = false)
|
||||||
args.push( { name : name, opt : opt || e != null, type : t, value: e } );
|
args.push( { name : name, opt : opt || e != null, type : t, value: e } );
|
||||||
|
|
||||||
public function init(name:String, pos:Position, with:FieldInit, ?prepend:Bool) {
|
public function init(name:String, pos:Position, with:FieldInit, ?options:{ ?prepend:Bool, ?bypass:Bool }) {
|
||||||
|
if (options == null)
|
||||||
|
options = {};
|
||||||
var e =
|
var e =
|
||||||
switch with {
|
switch with {
|
||||||
case Arg(t, noPublish):
|
case Arg(t, noPublish):
|
||||||
@@ -84,8 +86,12 @@ class Constructor {
|
|||||||
|
|
||||||
var tmp = MacroApi.tempName();
|
var tmp = MacroApi.tempName();
|
||||||
|
|
||||||
|
if (options.bypass) {
|
||||||
addStatement(macro @:pos(pos) if (false) { var $tmp = this.$name; $i{tmp} = $e; }, true);
|
addStatement(macro @:pos(pos) if (false) { var $tmp = this.$name; $i{tmp} = $e; }, true);
|
||||||
addStatement(macro @:pos(pos) (untyped this).$name = $e, prepend);
|
addStatement(macro @:pos(pos) (untyped this).$name = $e, options.prepend);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
addStatement(macro @:pos(pos) this.$name = $e, options.prepend);
|
||||||
}
|
}
|
||||||
public inline function publish()
|
public inline function publish()
|
||||||
if (isPublic == null)
|
if (isPublic == null)
|
||||||
|
|||||||
Reference in New Issue
Block a user