- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 162
Better support for generics via Class @generic tags #743
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
82acb90    to
    1164162      
    Compare
  
    | @castwide, in regards of: 
 Here you can find the draft PRs: 
 | 
| Thanks, @lekemula! I've been thinking about better ways to handle parametrized type inference, and your solution is very close to how I pictured it. Good to see that it also works with multiple parameters, e.g., when a Hash-like object needs key and value parameters: # @param Key
# @param Value
class Map
  # @yieldparam [param<Key>]
  # @yieldparam [param<Value>]
  def each(&block); end
end
# @return [Map<String, Integer>]
def map_method
  Map.new
end
map_method.each do |key, value|
  key._ # Completion for String
  value._ # Completion for Integer
endYARD doesn't complain about  I can think of a couple ways to extend the syntax around this feature, but we can probably leave those to future enhancements. As for the  | 
| I opened a YARD issue to ask about the param syntax and he made a strong argument for using a custom tag instead of repurposing the  My example, modified: # @generic [Key, Value]
class Map
  # @yieldparam [param<Key>]
  # @yieldparam [param<Value>]
  def each(&block); end
end
# @return [Map<String, Integer>]
def map_method
  Map.new
end
map_method.each do |key, value|
  key._ # Completion for String
  value._ # Completion for Integer
endWhat do you think, @lekemula? | 
| It also occurred to me that we can bypass the need for a class tag if we can reference the type parameters by index: class Map
  # @yieldparam [param<0>]
  # @yieldparam [param<1>]
  def each(&block); end
end | 
| @castwide Thanks for starting the discussion there! I also like the  
 My main concern, however, is ensuring that  Regarding the "indexed parameters" approach, I have mixed feelings. On one hand, it removes the need to manually add extra tags to the class. On the other hand, it feels somewhat obscure to me. In the age of AI, typing feels less and less like a burden - especially for trivial annotations like YARD - not that it ever really mattered to me. I also think we might lose the "indication" that @lsegal mentions in his feedback. However, one could argue that this is more of yard's responsibility rather than the LSP's. Additionally, this approach seems somewhat incompatible with RBS. As far as I know, we’d need to map "named generics" to "indexed generics/params," which could introduce additional complexity. If those mapped RBS indexed generics also appear in method documentation (in place of  TL;DR: I’m open to both approaches, but I prefer the  | 
| Good points about named vs. indexed parameters. Let's go with the  I've been planning to publish a separate  For now, we can add  If you want any help updating the PR, just let me know. | 
| 
 I'm not exactly sure how solargraph works, but if you're in charge of running  YARD::Tags::Library.define_tag("Generic", :generic, :with_types)In the case of running with  This would allow you to parse these tags regardless of if library has done so (though they probably would want to in order to generate their own docs). | 
| @@ -1,5 +1,7 @@ | |||
| # frozen_string_literal: true | |||
|  | |||
| require 'yard-solargraph' | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was needed for the unit test to pass.
| Thanks @lsegal, for your helpful information! 🙏 
 As far as I know, Solargraph recommends running  @castwide will you be able to look into this, or should I give it a try on a separate PR? | 
| Thanks, @lekemula! This is awesome. Good call on renaming  Along the same lines, do you think we should use  # @generic T
class Example
  # @yieldparam [generic<T>]
  def evaluate; end
endRegarding  | 
e57fc27    to
    9b8f128      
    Compare
  
    | 💯 I've also started work on the yard-solargraph plugin. | 
| 
 Appreciate that @castwide and thanks for the great feedback. That will be really helpful in allowing third-party gems to provide a better developer experience for their users—hoping it gets adopted by those already using YARD comments! | 
These should be generated by rbs signatures and should work properly after castwide#743
These should be generated by rbs signatures and should work properly after castwide#743
These should be generated by rbs signatures and should work properly after castwide#743
* Require Ruby >= 3 * Remove redundant YIELDPARAMS backfills These should be generated by rbs signatures and should work properly after #743 --------- Co-authored-by: Fred Snyder <[email protected]>


Closes: #681
This PR adds type inference for generics/parameterized params for
@returnand@yieldparamtags.I went with
@paraminstead of adding a custom tag for simplicity reasons. The tag is already parsed by YARDoc. Also, I think it's better to have fewer tags for developers to memorize.Does it make sense to you? Let me know if you have another opinion here.
Screenshots
Next steps
Adjust documentation accordingly based on inferred types - right now raw yardoc
[param<...>]is returned.Example
Deprecate
@return_single_parameterand@yieldparam_single_parameter(?)