lsegal / yard

YARD is a Ruby Documentation tool. The Y stands for "Yay!"
http://yardoc.org
MIT License
1.94k stars 397 forks source link

Refer to the type of block result in the return type signature. #891

Closed glebm closed 9 years ago

glebm commented 9 years ago

It would be nice to be able to refer to the type of the block result in the return type signature when a specific type is not required (otherwise @yieldparam could be used). Strawman:

# @param [Array<number>]
# @yield [number]
# @yieldparam number [Fixnum]
# @return [Array<of block results>]
def map_squares(numbers)
  numbers.map { |number| yield number * number }
end
lsegal commented 9 years ago

You can already do this. Type specifiers are freeform text. That said, a type contract with no specific type requirement is Object.

glebm commented 9 years ago

It would be nice if it would be possible encode the requirement that is more specific than Object:

Given a block with return type T, this function will return an Array<T>.

I guess what I am asking for is some form of generic types.

lsegal commented 9 years ago

Given a block with return type T, this function will return an Array<T>.

You can specify it in that way. As mentioned, type specifiers are freeform text, there is no limitation on how you can specify types. If your users understand what Array<T> means in the context of your library, go for it.

glebm commented 9 years ago

Freeform text cannot be used by tools such as RubyMine for type-inference, which it currently has excellent support for with YARD.

lsegal commented 9 years ago

Then it sounds like this issue should be opened against RubyMine, since no decision here would change the behavior there.

glebm commented 9 years ago

A structured format of generic types would enable tools to support these types for type-inference. Currently the blocker is that no structured format exists.

glebm commented 9 years ago

Then it sounds like this issue should be opened against RubyMine, since no decision here would change the behavior there.

This would require strong AI...

glebm commented 9 years ago

If the need for this is recognized I can start thinking about the specification.

lsegal commented 9 years ago

A structured format of generic types would enable tools to support it for type-inference. Currently the blocker is that no structured format exists.

This is not a "blocker"; quite explicitly, YARD is not blocking tooling from interpreting type specifications in any way that suits them best. RubyMine is free to define its own syntax to support template-style generics, and other tools are free to start supporting this syntax as well.

In short, YARD does not parse the type specifications, so defining a "structured format" would be a no-op from our side, since the format is not used anywhere. It's up to consumers to define their appropriate formats. There's no plan to define a hard syntax for type specifications in YARD for exactly this reason.

lsegal commented 9 years ago

If you're looking for a syntax to follow in your codebase, consider adopting portions from DiamondbackRuby (http://www.cs.umd.edu/projects/PL/druby/) or Rust (http://www.rust-lang.org/). If it works for you, shop it around to the tooling you use that interprets these types (i.e. RubyMine) and convince them to support it.

glebm commented 9 years ago

YARD does not parse the type specifications, so defining a "structured format" would be a no-op from our side, since the format is not used anywhere.

For example, if generic types are denoted with <Identifier: Types>:

# @yieldreturn [<T: Comparable>]
# @return [Array<T>]

YARD can then render nice documentation, such as:

Yield Returns:

  • (A type T that includes {Comparable})

Returns:

  • (Array<{T}>)

Where the second T would link to where T is declared, i.e. the Yield Returns description.

Otherwise, perhaps not a hard format but a recommendation? I am afraid of the fragmentation that will happen if the tools are left on their own.

lsegal commented 9 years ago

There are no plans for YARD to interpret type specifications. For that reason, there are no plans to define a specification syntax. This has been the case since YARD was created, and existing tools have not fragmented, so I think we're fine. The Ruby community has a strong sense about converging on good conventions, and I trust that tooling will do just that if there is a need.

Marking this as wontfix. If tools were to start supporting templated generics, we can revisit the issue, but as it stands now it's YAGNI, and it would be a waste of time to implement a specification without any signoff from tools that they will implement similar support.

ypresto commented 7 years ago

There is new code completion plugin for an editor, which is implemented using yard's type information. https://marketplace.visualstudio.com/items?itemName=castwide.solargraph https://github.com/castwide/solargraph

It can complete ['a', 'b', 'c'].join(...) well but not map { ... }. I found that to support completion of map, we need to specify a relationship between @return and @yieldreturn types.