Compare commits
21 Commits
no-reflect
...
isAbstract
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59d7407d1b | ||
|
|
0680220a77 | ||
|
|
acaedc170a | ||
|
|
8b9dbba624 | ||
|
|
f9348d4a46 | ||
|
|
6f4e6b9227 | ||
|
|
59135d5cea | ||
|
|
4accf55b41 | ||
|
|
fd3b01ef0f | ||
|
|
5825c2b617 | ||
|
|
328a8476a5 | ||
|
|
1589665652 | ||
|
|
08f15a6739 | ||
|
|
b5e992b820 | ||
|
|
8c50dcf04b | ||
|
|
4bc63c6eb0 | ||
|
|
acb7237ae4 | ||
|
|
e3bac681ce | ||
|
|
34516086c9 | ||
|
|
b1e7bf51cf | ||
|
|
d5186f2fa2 |
@@ -22,7 +22,7 @@ install:
|
||||
- lix download
|
||||
|
||||
script:
|
||||
- lix run travix node -lib hx3compat
|
||||
- lix run travix node
|
||||
|
||||
jobs:
|
||||
include:
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
-D hx3compat=1.0.0
|
||||
# @install: lix --silent download "haxelib:/hx3compat#1.0.0" into hx3compat/1.0.0/haxelib
|
||||
-cp ${HAXE_LIBCACHE}/hx3compat/1.0.0/haxelib/std
|
||||
# @install: lix --silent download "haxelib:/hx3compat#1.0.3" into hx3compat/1.0.3/haxelib
|
||||
-cp ${HAXE_LIBCACHE}/hx3compat/1.0.3/haxelib/std
|
||||
-D hx3compat=1.0.3
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# @install: lix --silent download "haxelib:hxnodejs#4.0.9" into hxnodejs/4.0.9/haxelib
|
||||
-D hxnodejs=4.0.9
|
||||
-cp ${HAXESHIM_LIBCACHE}/hxnodejs/4.0.9/haxelib/src
|
||||
-D nodejs
|
||||
# @install: lix --silent download "haxelib:/hxnodejs#12.0.0" into hxnodejs/12.0.0/haxelib
|
||||
-cp ${HAXE_LIBCACHE}/hxnodejs/12.0.0/haxelib/src
|
||||
-D hxnodejs=12.0.0
|
||||
--macro allowPackage('sys')
|
||||
--macro _hxnodejs.VersionWarning.include()
|
||||
# should behave like other target defines and not be defined in macro context
|
||||
--macro define('nodejs')
|
||||
|
||||
24
haxelib.json
24
haxelib.json
@@ -1,20 +1,20 @@
|
||||
{
|
||||
"name": "tink_macro",
|
||||
"license": "MIT",
|
||||
"description": "The macro toolkit ;)",
|
||||
"classPath": "src",
|
||||
"dependencies": {
|
||||
"tink_core": ""
|
||||
},
|
||||
"url": "https://github.com/haxetink/tink_macro",
|
||||
"contributors": [
|
||||
"back2dos"
|
||||
],
|
||||
"version": "0.21.1",
|
||||
"releasenote": "Fix issue with build field retrieval.",
|
||||
"tags": [
|
||||
"tink",
|
||||
"macro",
|
||||
"utility"
|
||||
],
|
||||
"classPath": "src",
|
||||
"description": "The macro toolkit ;)",
|
||||
"contributors": [
|
||||
"back2dos"
|
||||
],
|
||||
"releasenote": "Compat with haxe 4 rc4 onward.",
|
||||
"version": "0.18.0",
|
||||
"url": "http://haxetink.org/tink_macro",
|
||||
"dependencies": {
|
||||
"tink_core": ""
|
||||
}
|
||||
"license": "MIT"
|
||||
}
|
||||
@@ -8,6 +8,8 @@ using StringTools;
|
||||
|
||||
typedef Positions = tink.macro.Positions;
|
||||
typedef ExprTools = haxe.macro.ExprTools;
|
||||
typedef TypedExprTools = haxe.macro.TypedExprTools;
|
||||
typedef TypedExprs = tink.macro.TypedExprs;
|
||||
typedef Exprs = tink.macro.Exprs;
|
||||
typedef Functions = tink.macro.Functions;
|
||||
typedef Metadatas = tink.macro.Metadatas;
|
||||
@@ -52,9 +54,16 @@ class MacroApi {
|
||||
|
||||
static public var completionPoint(default, null):Option<{
|
||||
var file(default, never):String;
|
||||
var content(default, never):Null<String>;
|
||||
var pos(default, never):Int;
|
||||
}>;
|
||||
|
||||
static public function getBuildFields():Option<Array<haxe.macro.Expr.Field>>
|
||||
return switch completionPoint {
|
||||
case Some(v) if (v.content != null && (v.content.charAt(v.pos - 1) == '@' || (v.content.charAt(v.pos - 1) == ':' && v.content.charAt(v.pos - 2) == '@'))): None;
|
||||
default: Some(haxe.macro.Context.getBuildFields());
|
||||
}
|
||||
|
||||
static public var args(default, null):Iterable<String>;
|
||||
static var initialized = initArgs();
|
||||
|
||||
@@ -71,12 +80,15 @@ class MacroApi {
|
||||
params:{
|
||||
file:String,
|
||||
offset:Int,
|
||||
contents:String,
|
||||
}
|
||||
} = haxe.Json.parse(arg);
|
||||
|
||||
switch payload {
|
||||
case { jsonrpc: '2.0', method: 'display/completion' }:
|
||||
Some({
|
||||
file: payload.params.file,
|
||||
content: payload.params.contents,
|
||||
pos: payload.params.offset,
|
||||
});
|
||||
default: None;
|
||||
|
||||
@@ -35,7 +35,7 @@ class BuildCache {
|
||||
|
||||
@:persistent static var cache = new Map();
|
||||
|
||||
static public function getType3(name, ?types, ?pos:Position, build:BuildContext3->TypeDefinition) {
|
||||
static public function getType3(name, ?types, ?pos:Position, build:BuildContext3->TypeDefinition, ?normalizer:Type->Type) {
|
||||
if (types == null)
|
||||
switch Context.getLocalType() {
|
||||
case TInst(_.toString() == name => true, [t1, t2, t3]):
|
||||
@@ -55,10 +55,10 @@ class BuildCache {
|
||||
pos: ctx.pos,
|
||||
name: ctx.name,
|
||||
usings: ctx.usings
|
||||
}));
|
||||
}), normalizer);
|
||||
}
|
||||
|
||||
static public function getTypeN(name, ?types, ?pos:Position, build:BuildContextN->TypeDefinition) {
|
||||
static public function getTypeN(name, ?types, ?pos:Position, build:BuildContextN->TypeDefinition, ?normalizer:Type->Type) {
|
||||
|
||||
if (pos == null)
|
||||
pos = Context.currentPos();
|
||||
@@ -86,10 +86,10 @@ class BuildCache {
|
||||
pos: ctx.pos,
|
||||
name: ctx.name,
|
||||
usings: ctx.usings
|
||||
}));
|
||||
}), normalizer);
|
||||
}
|
||||
|
||||
static public function getType2(name, ?types, ?pos:Position, build:BuildContext2->TypeDefinition) {
|
||||
static public function getType2(name, ?types, ?pos:Position, build:BuildContext2->TypeDefinition, ?normalizer:Type->Type) {
|
||||
if (types == null)
|
||||
switch Context.getLocalType() {
|
||||
case TInst(_.toString() == name => true, [t1, t2]):
|
||||
@@ -107,7 +107,7 @@ class BuildCache {
|
||||
pos: ctx.pos,
|
||||
name: ctx.name,
|
||||
usings: ctx.usings
|
||||
}));
|
||||
}), normalizer);
|
||||
}
|
||||
|
||||
static public function getParams(name:String, ?pos:Position)
|
||||
@@ -130,14 +130,14 @@ class BuildCache {
|
||||
default: pos.makeFailure('too many parameters');
|
||||
});
|
||||
|
||||
static public function getType(name, ?type, ?pos:Position, build:BuildContext->TypeDefinition) {
|
||||
static public function getType(name, ?type, ?pos:Position, build:BuildContext->TypeDefinition, ?normalizer:Type->Type) {
|
||||
|
||||
if (type == null)
|
||||
type = getParam(name, pos).sure();
|
||||
|
||||
var forName =
|
||||
switch cache[name] {
|
||||
case null: cache[name] = new Group(name);
|
||||
case null: cache[name] = new Group(name, normalizer);
|
||||
case v: v;
|
||||
}
|
||||
|
||||
@@ -155,10 +155,11 @@ private class Group {
|
||||
|
||||
var name:String;
|
||||
var counter = 0;
|
||||
var entries = new TypeMap<Entry>();
|
||||
var entries:TypeMap<Entry>;
|
||||
|
||||
public function new(name) {
|
||||
public function new(name, ?normalizer) {
|
||||
this.name = name;
|
||||
this.entries = new TypeMap(normalizer);
|
||||
}
|
||||
|
||||
public function get(type:Type, pos:Position, build:BuildContext->TypeDefinition):Type {
|
||||
|
||||
@@ -23,7 +23,10 @@ class ClassBuilder {
|
||||
target = Context.getLocalClass().get();
|
||||
|
||||
if (fields == null)
|
||||
fields = Context.getBuildFields();
|
||||
fields = switch MacroApi.getBuildFields() {
|
||||
case None: target.pos.error('Impossible to get builds fields now. Possible cause: https://github.com/HaxeFoundation/haxe/issues/9853');
|
||||
case Some(v): v;
|
||||
}
|
||||
|
||||
this.initializeFrom = fields;
|
||||
this.target = target;
|
||||
@@ -192,10 +195,14 @@ class ClassBuilder {
|
||||
return m;
|
||||
}
|
||||
|
||||
static public function run(plugins:Array<ClassBuilder->Void>, ?verbose) {
|
||||
var builder = new ClassBuilder();
|
||||
static public function run(plugins:Array<ClassBuilder->Void>, ?verbose)
|
||||
return switch MacroApi.getBuildFields() {
|
||||
case None: null;
|
||||
case Some(fields):
|
||||
var builder = new ClassBuilder(fields);
|
||||
for (p in plugins)
|
||||
p(builder);
|
||||
return builder.export(verbose);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,8 +95,12 @@ class Sisyphus {
|
||||
TPath(toTypePath(baseType, params));
|
||||
case TFun(args, ret):
|
||||
TFunction(
|
||||
[ for (a in args) a.opt ? nullable(toComplexType(a.t)) : toComplexType(a.t) ],
|
||||
toComplexType(ret));
|
||||
[for (a in args) {
|
||||
var t = #if haxe4 TNamed(a.name, #else ( #end toComplexType(a.t));
|
||||
if (a.opt) TOptional(t) else t;
|
||||
}],
|
||||
toComplexType(ret)
|
||||
);
|
||||
case TAnonymous(_.get() => { fields: fields }):
|
||||
TAnonymous([ for (cf in fields) toField(cf) ]);
|
||||
case TDynamic(t):
|
||||
|
||||
@@ -8,14 +8,33 @@ import haxe.macro.Type;
|
||||
using tink.MacroApi;
|
||||
|
||||
class TypeMap<V> extends BalancedTree<Type, V> implements IMap<Type, V> {
|
||||
var follow:Bool;
|
||||
var normalize:Type->Type;
|
||||
|
||||
public function new(?noFollow:Bool) {
|
||||
this.follow = noFollow != true;
|
||||
public function new(?normalize:Type->Type) {
|
||||
this.normalize = switch normalize {
|
||||
case null: function (t) return t.reduce();
|
||||
case fn: fn;
|
||||
}
|
||||
super();
|
||||
}
|
||||
|
||||
override function compare(k1:Type, k2:Type):Int
|
||||
return k1.compare(k2, follow);
|
||||
return normalize(k1).compare(normalize(k2), false);
|
||||
|
||||
static public function noFollow(t:Type)
|
||||
return t;
|
||||
|
||||
static public function keepNull(t:Type):Type
|
||||
return switch t {
|
||||
case TAbstract(_.get() => { name: 'Null', pack: [] }, [t])
|
||||
#if !haxe4 | TType(_.get() => { name: 'Null', pack: []}, [t]) #end
|
||||
:
|
||||
var ct = keepNull(t).toComplex({ direct: true });
|
||||
(macro : Null<$ct>).toType().sure();
|
||||
|
||||
case TLazy(f): keepNull(f());
|
||||
case TType(_, _): keepNull(Context.follow(t, true));
|
||||
default: t;
|
||||
}
|
||||
|
||||
}
|
||||
55
src/tink/macro/TypedExprs.hx
Normal file
55
src/tink/macro/TypedExprs.hx
Normal file
@@ -0,0 +1,55 @@
|
||||
package tink.macro;
|
||||
|
||||
import haxe.macro.Type;
|
||||
import haxe.ds.Option;
|
||||
using haxe.macro.Tools;
|
||||
|
||||
class TypedExprs {
|
||||
|
||||
static public function extractAll<T>(t:TypedExpr, f:TypedExpr->Option<T>):Array<T> {
|
||||
var out = [];
|
||||
function rec(t:TypedExpr)
|
||||
if (t != null) {
|
||||
switch f(t) {
|
||||
case Some(v): out.push(v);
|
||||
default:
|
||||
}
|
||||
t.iter(rec);
|
||||
}
|
||||
rec(t);
|
||||
return out;
|
||||
}
|
||||
|
||||
static public function extract<T>(t:TypedExpr, f:TypedExpr->Option<T>):Option<T> {
|
||||
try extractAll(t, function (t) {
|
||||
var ret = f(t);
|
||||
if (ret != None)
|
||||
throw ret;
|
||||
return ret;
|
||||
})
|
||||
catch (e:Option<Dynamic>) return cast e;
|
||||
return None;
|
||||
}
|
||||
|
||||
static public function isThis(t:TypedExpr):Bool
|
||||
return switch t {
|
||||
case null: false;
|
||||
case { expr: TConst(TThis) | TLocal({ name: '`this' })}: true;
|
||||
default: false;
|
||||
}
|
||||
|
||||
static public inline function hasThis(t)
|
||||
return contains(t, isThis);
|
||||
|
||||
static public function findAll(t:TypedExpr, f:TypedExpr->Bool):Array<TypedExpr>
|
||||
return extractAll(t, collect(f));
|
||||
|
||||
static public function find(t:TypedExpr, f:TypedExpr->Bool):Option<TypedExpr>
|
||||
return extract(t, collect(f));
|
||||
|
||||
static public function contains(t:TypedExpr, f:TypedExpr->Bool):Bool
|
||||
return find(t, f) != None;
|
||||
|
||||
static inline function collect(f)
|
||||
return function (t) return if (f(t)) Some(t) else None;
|
||||
}
|
||||
@@ -172,6 +172,9 @@ class Types {
|
||||
#if haxe4
|
||||
isExtern: field.isExtern,
|
||||
isFinal: field.isFinal,
|
||||
#if (haxe >= version("4.2.0-rc.1"))
|
||||
isAbstract: field.isAbstract,
|
||||
#end
|
||||
#end
|
||||
}:ClassField)
|
||||
]);
|
||||
@@ -258,8 +261,7 @@ class Types {
|
||||
return if (once) t else reduce(t, false);
|
||||
return switch type {
|
||||
case TAbstract(_.get() => { name: 'Null', pack: [] }, [t]): rec(t);
|
||||
case TLazy(f): rec(f());
|
||||
case TType(_, _): rec(Context.follow(type, once));
|
||||
case TLazy(_) | TType(_): rec(Context.follow(type, once));
|
||||
default: type;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
-cp tests
|
||||
-lib hx3compat
|
||||
-main Run
|
||||
1
tests/MyString.hx
Normal file
1
tests/MyString.hx
Normal file
@@ -0,0 +1 @@
|
||||
typedef MyString = String;
|
||||
@@ -19,6 +19,7 @@ class Run {
|
||||
macro static function test() {
|
||||
var runner = new TestRunner();
|
||||
tink.macro.ClassBuilder;
|
||||
tink.macro.BuildCache;
|
||||
for (c in cases)
|
||||
runner.add(c);
|
||||
runner.run();
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
package;
|
||||
|
||||
import haxe.unit.TestCase;
|
||||
import haxe.macro.Expr;
|
||||
|
||||
import tink.macro.TypeMap;
|
||||
using haxe.macro.Context;
|
||||
using tink.MacroApi;
|
||||
|
||||
class TypeMapTest extends TestCase {
|
||||
|
||||
function testMap() {
|
||||
var t = new TypeMap();
|
||||
var t1 = (macro [{ foo: [{ bar: '5' }]}]).typeof();
|
||||
var t2 = (macro [{ foo: [{ bar: 5 }]}]).typeof();
|
||||
var t1 = (macro [{ foo: [{ bar: '5' }]}]).typeof().sure();
|
||||
var t2 = (macro [{ foo: [{ bar: 5 }]}]).typeof().sure();
|
||||
|
||||
t.set(t1, 0);
|
||||
assertEquals(Lambda.count(t), 1);
|
||||
@@ -27,4 +27,22 @@ class TypeMapTest extends TestCase {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
function testNormalization() {
|
||||
for (settings in [
|
||||
{ count: 4, map: new TypeMap(TypeMap.noFollow)},
|
||||
{ count: 2, map: new TypeMap(TypeMap.keepNull)},
|
||||
{ count: 1, map: new TypeMap()},
|
||||
]) {
|
||||
|
||||
function set(ct:ComplexType)
|
||||
settings.map.set(ct.toType().sure(), ct);
|
||||
|
||||
set(macro : String);
|
||||
set(macro : MyString);
|
||||
set(macro : Null<String>);
|
||||
set(macro : Null<MyString>);
|
||||
|
||||
assertEquals(settings.count, Lambda.count(settings.map));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user