Search code examples
crystal-lang

Examine method metadata (i.e. arity, arg types, etc)


In Crystal, is it possible to view metadata on a type's method at compile time? For example, to determine the number of arguments the method accepts, what the type restrictions on the arguments are, etc.

Looking through the API, the compiler's Def and Arg macros have methods which supposedly return this meta information, but I can't see a way of accessing them. I suspect the meta information is only accessible by the compiler.


Solution

  • I found out how to do it. I was looking in the wrong place of the API. The Crystal::Macros::TypeNode has a methods macro which returns an array of method Def (which is how you can access them). It looks like the TypeNode class is the entry point to a lot of good macros.

    Usage example

    class Person
      def name(a)
        "John"
      end
    
      def test
        {{@type.methods.map(&.name).join(', ')}}
      end
    end
    

    Or

    {{@type.methods.first.args.first.name}}
    

    Simply returning the argument name posses an interesting problem, because, after the macro interpreter pastes it into the program, the compiler interprets the name as a variable (which makes sense).

    But the real value happens in being able to see the type restrictions of the method arguments

    class Public < Person
      def name(a : String)
        a
      end
    
      def max
        {{@type.methods.first.args.first.restriction}}
      end
    end
    
    Person.new.max # => String