Exact type to string conversion.
This commit is contained in:
@@ -2,6 +2,8 @@ package tink.macro;
|
|||||||
|
|
||||||
import haxe.macro.Expr;
|
import haxe.macro.Expr;
|
||||||
import haxe.macro.Type;
|
import haxe.macro.Type;
|
||||||
|
using haxe.macro.Tools;
|
||||||
|
using tink.MacroApi;
|
||||||
|
|
||||||
class Sisyphus {
|
class Sisyphus {
|
||||||
|
|
||||||
@@ -61,8 +63,7 @@ class Sisyphus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static public function toComplexType(type : Null<Type>) : Null<ComplexType> return {
|
||||||
public static function toComplexType(type : Null<Type>) : Null<ComplexType> return {
|
|
||||||
inline function direct()
|
inline function direct()
|
||||||
return Types.toComplex(type, { direct: true });
|
return Types.toComplex(type, { direct: true });
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -136,4 +137,61 @@ class Sisyphus {
|
|||||||
}],
|
}],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function exactBase<T:BaseType>(r:haxe.macro.Type.Ref<T>, params:Array<Type>) {
|
||||||
|
var t = r.get();
|
||||||
|
var isMain = !t.isPrivate && switch t.pack {
|
||||||
|
case []: t.module == t.name || t.module == 'StdTypes';
|
||||||
|
default: StringTools.endsWith(t.module, '.${t.name}');
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
if (isMain) t.pack.concat([t.name]).join('.')
|
||||||
|
else t.module + '.' + t.name
|
||||||
|
) + switch params {
|
||||||
|
case []: '';
|
||||||
|
case params:
|
||||||
|
'<${params.map(toExactString).join(', ')}>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static function exactAnonField(c:ClassField) {
|
||||||
|
var kw =
|
||||||
|
switch c.kind {
|
||||||
|
case FMethod(_): 'function';
|
||||||
|
case FVar(_):
|
||||||
|
if (c.isFinal) 'final' else 'var';
|
||||||
|
}
|
||||||
|
|
||||||
|
return [for (m in c.meta.get()) m.toString() + ' '].join('') + '$kw ${c.name}' + (switch c.kind {
|
||||||
|
case FVar(read, write):
|
||||||
|
(
|
||||||
|
if (c.isFinal || (read == AccNormal && write == AccNormal)) ''
|
||||||
|
else '(${read.accessToName()}, ${read.accessToName(false)})'
|
||||||
|
) + ':' + c.type.toExactString();
|
||||||
|
case FMethod(_):
|
||||||
|
switch haxe.macro.Context.follow(c.type) {
|
||||||
|
case TFun(arg, ret): exactSig(arg, ret, ':');
|
||||||
|
default: throw 'assert';
|
||||||
|
}
|
||||||
|
}) + ';';
|
||||||
|
}
|
||||||
|
|
||||||
|
static function exactSig(args:Array<{name:String, opt:Bool, t:Type}>, ret:Type, sep:String)
|
||||||
|
return '(${[for (a in args) (if (a.opt) '?' else '') + a.name + ':' + toExactString(a.t)].join(', ')})$sep${toExactString(ret)}';
|
||||||
|
|
||||||
|
static public function toExactString(t:Type)
|
||||||
|
return switch t {
|
||||||
|
case TMono(t): t.toString();
|
||||||
|
case TEnum(r, params): exactBase(r, params);
|
||||||
|
case TInst(r, params): exactBase(r, params);
|
||||||
|
case TType(r, params): exactBase(r, params);
|
||||||
|
case TAbstract(r, params): exactBase(r, params);
|
||||||
|
case TFun(args, ret): exactSig(args, ret, '->');
|
||||||
|
case TAnonymous(a): '{ ${[for (f in a.get().fields) exactAnonField(f)].join(' ')} }';
|
||||||
|
case TDynamic(null): 'Dynamic';
|
||||||
|
case TDynamic(t): 'Dynamic<${toExactString(t)}>';
|
||||||
|
case TLazy(f): toExactString(f());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -221,6 +221,10 @@ class Types {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// like haxe.macro.TypeTools.toString, but not lossy
|
||||||
|
static public function toExactString(t:Type)
|
||||||
|
return Sisyphus.toExactString(t);
|
||||||
|
|
||||||
static public function toString(t:ComplexType)
|
static public function toString(t:ComplexType)
|
||||||
return new Printer().printComplexType(t);
|
return new Printer().printComplexType(t);
|
||||||
|
|
||||||
|
8
tests/Dummy.hx
Normal file
8
tests/Dummy.hx
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
class Dummy {
|
||||||
|
public function new() {}
|
||||||
|
static public var p(default, never) = new Private();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Private {
|
||||||
|
public function new() {}
|
||||||
|
}
|
20
tests/ExactStrings.hx
Normal file
20
tests/ExactStrings.hx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import haxe.macro.Context;
|
||||||
|
import haxe.macro.Context.typeof;
|
||||||
|
using tink.MacroApi;
|
||||||
|
|
||||||
|
class ExactStrings extends Base {
|
||||||
|
function test() {
|
||||||
|
function expect(s:String, e, ?pos)
|
||||||
|
assertEquals(s, typeof(e).toExactString(), pos);
|
||||||
|
|
||||||
|
expect('Dummy', macro new Dummy());
|
||||||
|
expect('nested.Dummy', macro new nested.Dummy());
|
||||||
|
expect('Dummy.Private', macro Dummy.p);
|
||||||
|
expect('nested.Dummy.Private', macro nested.Dummy.p);
|
||||||
|
expect('{ @foo var x:Int; }', macro (null:{@foo var x:Int;}));
|
||||||
|
expect('{ @bar var x:Int; }', macro (null:{@bar var x:Int;}));
|
||||||
|
expect('{ var x:Int; var y:Int; }', macro (null:{x:Int,y:Int}));
|
||||||
|
expect('{ var x:Int; var y:Int; }', macro (null:{y:Int,x:Int}));
|
||||||
|
expect('{ function foo(x:Int, ?y:Int):Void; }', macro (null:{ function foo(x:Int, ?y:Int):Void; }));
|
||||||
|
}
|
||||||
|
}
|
@@ -1,6 +1,9 @@
|
|||||||
package ;
|
package ;
|
||||||
|
|
||||||
import haxe.unit.*;
|
import haxe.unit.*;
|
||||||
|
#if macro
|
||||||
|
using haxe.macro.Tools;
|
||||||
|
#end
|
||||||
|
|
||||||
class Run {
|
class Run {
|
||||||
#if !macro
|
#if !macro
|
||||||
@@ -14,6 +17,7 @@ class Run {
|
|||||||
new TypeMapTest(),
|
new TypeMapTest(),
|
||||||
new Functions(),
|
new Functions(),
|
||||||
new Misc(),
|
new Misc(),
|
||||||
|
new ExactStrings(),
|
||||||
];
|
];
|
||||||
#end
|
#end
|
||||||
macro static function test() {
|
macro static function test() {
|
||||||
|
10
tests/nested/Dummy.hx
Normal file
10
tests/nested/Dummy.hx
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package nested;
|
||||||
|
|
||||||
|
class Dummy {
|
||||||
|
public function new() {}
|
||||||
|
static public var p(default, never) = new Private();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Private {
|
||||||
|
public function new() {}
|
||||||
|
}
|
Reference in New Issue
Block a user