COMMUNITY

Can compiler conditions be parsed/evaluated in Haxe macro mode?

macro

(Seb) #1

That question may sound a bit strange, so let me give you some context…

I wrote https://vegardit.github.io/haxe-doctest/ which is a Python doctest inspired testing library.

What it basically does is to scan the haxedoc of modules looking for unit test assertions, which are test expressions prefixed with “>>>”. For example:

class MyTools {

    /**
     * <pre><code>
     * >>> MyTools.isValidName(null)   == false
     * >>> MyTools.isValidName("")     == false
     * >>> MyTools.isValidName("John") == true
     * </code></pre>
     */
    public static function isValidName(str:String):Bool {
        return str != null && str.length > 0;
    }
}

The search for test expressions is currently done by reading the string content of the haxe modules and iterating over all lines looking for lines starting “* >>>” while ignoring any leading whitespaces. Then I am using macro code to parse the expression and generate actual haxe code in a separate test class.

What I am now looking for is a way to also respect compiler conditionals found in classes. Say when a class contains some methods only for sys target, and I execute the doctest runner on JavaScript, the macro code should not generate test methods for doctest expressions found in the haxedoc of sys target related method’s. E.g. for the following code:

class MyTools {

    /**
     * <pre><code>
     * >>> MyTools.foo(null)   == false
     * </code></pre>
     */
    public static function foo(str:String):Bool {
        // some code
    }

    #if sys
    /**
     * <pre><code>
     * >>> MyTools.bar(null)   == false 
     * </code></pre>
     */
    public static function bar(str:String):Bool {
        // some code
    }
    #end
}

If I run the doctest generator on JS for this example, no doctest assertions of the bar() method should be transformed (and thus tested).

So I am asking for ideas how - while the MyTools class is scanned for doctest expressions in macro mode - can I - with the least effort - decide which of the expressions to transform into actual test methods and which not based on the currently selected target.

For example when I am iterating over the lines of a haxe module’s string content and I encounter a complex conditional like #if (myCustomDefine && (flash || (js && !phantomjs))) can I then somehow ask some magic Haxe macro API to actually evaluate the found condition (myCustomDefine && (flash || (js && !phantomjs))) in macro mode ( @back2dos ? :wink: ) to then make the decision if the doctest lines found within this conditional block should be considered or ignored when generating the test code.

But maybe there exists a completely different approach to achieve what I am actually looking for.

Thanks for any hints in advance!


(Juraj Kirchheim) #2

You can get the doc strings of what actually gets compiled (honoring for example conditional compilation) in a typed manner: https://api.haxe.org/haxe/macro/ClassField.html#doc

Note that for Haxe 3 it requires -D use-rtti-doc to “Allows access to documentation during compilation” (otherwise the doc field is not populated).

My personal suggestion would be to parse those doc strings as markdown, since fenced code blocks allow you to specify language (so you could differentiate spec vs. examples).


(Seb) #3

Jurai, thanks for your response. In the meanwhile I implemented something with the help of hscript, however accessing the typed classes instead of manually string-parsing the source files definitely sounds like the better approach.

I am going to look into it. Thanks again!

Note to myself: As of Haxe 4 Preview 5 -D use-rtti-doc is not required anymore: https://github.com/HaxeFoundation/haxe/issues/7493