diff --git a/Steepfile b/Steepfile index f799db461..81d1ef930 100644 --- a/Steepfile +++ b/Steepfile @@ -9,7 +9,7 @@ target :lib do "lib/rbs/test.rb" ) - library "set", "pathname", "json", "logger", "monitor", "tsort", "uri", 'dbm', 'pstore', 'singleton', 'shellwords', 'fileutils', 'find', 'digest' + library "set", "pathname", "json", "logger", "monitor", "tsort", "uri", 'dbm', 'pstore', 'singleton', 'shellwords', 'fileutils', 'find', 'digest', 'ripper' signature 'stdlib/yaml/0' signature "stdlib/strscan/0/" signature "stdlib/optparse/0/" diff --git a/sig/shims/ripper.rbs b/sig/shims/ripper.rbs deleted file mode 100644 index 6f8b1d769..000000000 --- a/sig/shims/ripper.rbs +++ /dev/null @@ -1,8 +0,0 @@ -class Ripper - def self.lex: (String src, ?String filename, ?Integer lineno, ?raise_errors: bool) -> Array[[[Integer, Integer], Symbol, String, Lexer::State]] - - class Lexer - class State - end - end -end diff --git a/stdlib/ripper/0/ripper.rbs b/stdlib/ripper/0/ripper.rbs new file mode 100644 index 000000000..091dbcfc2 --- /dev/null +++ b/stdlib/ripper/0/ripper.rbs @@ -0,0 +1,1650 @@ +# +# Ripper is a Ruby script parser. +# +# You can get information from the parser with event-based style. Information +# such as abstract syntax trees or simple lexical analysis of the Ruby program. +# +# ## Usage +# +# Ripper provides an easy interface for parsing your program into a symbolic +# expression tree (or S-expression). +# +# Understanding the output of the parser may come as a challenge, it's +# recommended you use PP to format the output for legibility. +# +# require 'ripper' +# require 'pp' +# +# pp Ripper.sexp('def hello(world) "Hello, #{world}!"; end') +# #=> [:program, +# [[:def, +# [:@ident, "hello", [1, 4]], +# [:paren, +# [:params, [[:@ident, "world", [1, 10]]], nil, nil, nil, nil, nil, nil]], +# [:bodystmt, +# [[:string_literal, +# [:string_content, +# [:@tstring_content, "Hello, ", [1, 18]], +# [:string_embexpr, [[:var_ref, [:@ident, "world", [1, 27]]]]], +# [:@tstring_content, "!", [1, 33]]]]], +# nil, +# nil, +# nil]]]] +# +# You can see in the example above, the expression starts with `:program`. +# +# From here, a method definition at `:def`, followed by the method's identifier +# `:@ident`. After the method's identifier comes the parentheses `:paren` and +# the method parameters under `:params`. +# +# Next is the method body, starting at `:bodystmt` (`stmt` meaning statement), +# which contains the full definition of the method. +# +# In our case, we're simply returning a String, so next we have the +# `:string_literal` expression. +# +# Within our `:string_literal` you'll notice two `@tstring_content`, this is the +# literal part for `Hello, ` and `!`. Between the two `@tstring_content` +# statements is a `:string_embexpr`, where *embexpr* is an embedded expression. +# Our expression consists of a local variable, or `var_ref`, with the identifier +# (`@ident`) of `world`. +# +# ## Resources +# +# * [Ruby +# Inside](http://www.rubyinside.com/using-ripper-to-see-how-ruby-is-parsing- +# your-code-5270.html) +# +# +# ## Requirements +# +# * ruby 1.9 (support CVS HEAD only) +# * bison 1.28 or later (Other yaccs do not work) +# +# +# ## License +# +# Ruby License. +# +# * Minero Aoki +# * aamine@loveruby.net +# * http://i.loveruby.net +# +class Ripper + # + # This array contains name of all ripper events. + # + EVENTS: Array[Symbol] + + EXPR_ARG: Integer + + EXPR_ARG_ANY: Integer + + EXPR_BEG: Integer + + EXPR_BEG_ANY: Integer + + EXPR_CLASS: Integer + + EXPR_CMDARG: Integer + + EXPR_DOT: Integer + + EXPR_END: Integer + + EXPR_ENDARG: Integer + + EXPR_ENDFN: Integer + + EXPR_END_ANY: Integer + + EXPR_FITEM: Integer + + EXPR_FNAME: Integer + + EXPR_LABEL: Integer + + EXPR_LABELED: Integer + + EXPR_MID: Integer + + EXPR_NONE: Integer + + EXPR_VALUE: Integer + + # + # This array contains name of parser events. + # + PARSER_EVENTS: Array[Symbol] + + PARSER_EVENT_TABLE: Hash[Symbol, Integer] + + # + # This array contains name of scanner events. + # + SCANNER_EVENTS: Array[Symbol] + + SCANNER_EVENT_TABLE: Hash[Symbol, Integer] + + # + # version of Ripper + # + Version: String + + # + # This class handles only scanner events, which are dispatched in the 'right' + # order (same with input). + # + class Filter + private + + # + # Creates a new Ripper::Filter instance, passes parameters `src`, `filename`, + # and `lineno` to Ripper::Lexer.new + # + # The lexer is for internal use only. + # + def initialize: (File | _Gets | String src, ?String filename, ?Integer lineno) -> void + + public + + # + # The column number of the current token. This value starts from 0. This method + # is valid only in event handlers. + # + def column: () -> Integer? + + # + # The file name of the input. + # + def filename: () -> String + + # + # The line number of the current token. This value starts from 1. This method is + # valid only in event handlers. + # + def lineno: () -> Integer? + + # + # Starts the parser. `init` is a data accumulator and is passed to the next + # event handler (as of Enumerable#inject). + # + def parse: (?untyped init) -> untyped + + # + # The scanner's state of the current token. This value is the bitwise OR of zero + # or more of the `Ripper::EXPR_*` constants. + # + def state: () -> Ripper::Lexer::State + + private + + # + # This method is called when some event handler is undefined. `event` is + # :on_XXX, `token` is the scanned token, and `data` is a data accumulator. + # + # The return value of this method is passed to the next event handler (as of + # Enumerable#inject). + # + def on_default: (untyped event, untyped token, untyped data) -> untyped + end + + class Lexer < Ripper + class Elem + attr_accessor event: Symbol + + attr_accessor message: String? + attr_accessor pos: [ Integer, Integer ] + + attr_accessor state: Ripper::Lexer::State + attr_accessor tok: String + + private + + # + # + def initialize: ([ Integer, Integer ] pos, Symbol event, String tok, Integer | Ripper::Lexer::State state, ?String? message) -> void + + public + + # + # + def []: (0 | :pos) -> [ Integer, Integer ] + | (1 | :event) -> Symbol + | (2 | :tok) -> String + | (3 | :state) -> Ripper::Lexer::State + | (4 | :message) -> String? + | (Integer | Symbol) -> untyped + | (untyped) -> nil + + # + # + def to_a: () -> [ [ Integer, Integer ], Symbol, String, Ripper::Lexer::State, String ] + | () -> [ [ Integer, Integer ], Symbol, String, Ripper::Lexer::State ] + end + + class State + attr_reader to_int: Integer + attr_reader to_s: String + + private + + # + # + def initialize: (Integer | State i) -> void + + public + + # + # + def &: (Integer i) -> State + + # + # + def ==: (Integer | State i) -> bool + + # + # + def []: (0 | :to_int index) -> (Integer | State) + | (1 | :to_s index) -> String + | (untyped) -> nil + + # + # + def allbits?: (int i) -> bool + + # + # + def anybits?: (int i) -> bool + + # + # + def nobits?: (int i) -> bool + + alias to_i to_int + + # + # + def |: (Integer i) -> State + end + attr_reader errors: Array[Lexer::Elem] + + alias compile_error on_error1 + def lex: (?raise_errors: boolish) -> Array[[ [ Integer, Integer ], Symbol, String, Lexer::State ]] + + alias on_CHAR _push_token + + alias on___end__ _push_token + + alias on_alias_error on_error2 + + alias on_assign_error on_error2 + + alias on_backref _push_token + + alias on_backtick _push_token + + alias on_class_name_error on_error2 + + alias on_comma _push_token + + alias on_comment _push_token + + alias on_const _push_token + + alias on_cvar _push_token + + alias on_embdoc _push_token + + alias on_embdoc_beg _push_token + + alias on_embdoc_end _push_token + + alias on_embexpr_beg _push_token + + alias on_embexpr_end _push_token + + alias on_embvar _push_token + + alias on_float _push_token + + alias on_gvar _push_token + + alias on_ident _push_token + + alias on_ignored_nl _push_token + + alias on_ignored_sp _push_token + + alias on_imaginary _push_token + + alias on_int _push_token + + alias on_ivar _push_token + + alias on_kw _push_token + + alias on_label _push_token + + alias on_label_end _push_token + + alias on_lbrace _push_token + + alias on_lbracket _push_token + + alias on_lparen _push_token + + alias on_nl _push_token + + alias on_op _push_token + + alias on_param_error on_error2 + + alias on_parse_error on_error1 + + alias on_period _push_token + + alias on_qsymbols_beg _push_token + + alias on_qwords_beg _push_token + + alias on_rational _push_token + + alias on_rbrace _push_token + + alias on_rbracket _push_token + + alias on_regexp_beg _push_token + + alias on_regexp_end _push_token + + alias on_rparen _push_token + + alias on_semicolon _push_token + + alias on_sp _push_token + + alias on_symbeg _push_token + + alias on_symbols_beg _push_token + + alias on_tlambda _push_token + + alias on_tlambeg _push_token + + alias on_tstring_beg _push_token + + alias on_tstring_content _push_token + + alias on_tstring_end _push_token + + alias on_words_beg _push_token + + alias on_words_sep _push_token + def parse: (?raise_errors: boolish) -> Array[Lexer::Elem] + + def scan: (?raise_errors: boolish) -> Array[Lexer::Elem] + + def tokenize: (?raise_errors: boolish) -> Array[String] + + private + + def _push_token: (untyped tok) -> Lexer::Elem + + def on_error1: (untyped mesg) -> Array[Lexer::Elem] + + def on_error2: (untyped mesg, untyped elem) -> Array[Lexer::Elem] + + def on_heredoc_beg: (untyped tok) -> untyped + + def on_heredoc_dedent: (untyped v, untyped w) -> untyped + + def on_heredoc_end: (untyped tok) -> untyped + end + + class SexpBuilder < Ripper + attr_reader error: untyped + + alias compile_error on_error + def on_BEGIN: (*untyped args) -> untyped + + def on_CHAR: (untyped tok) -> untyped + + def on_END: (*untyped args) -> untyped + + def on___end__: (untyped tok) -> untyped + + def on_alias: (*untyped args) -> untyped + + def on_alias_error: (*untyped args) -> untyped + + def on_aref: (*untyped args) -> untyped + + def on_aref_field: (*untyped args) -> untyped + + def on_arg_ambiguous: (*untyped args) -> untyped + + def on_arg_paren: (*untyped args) -> untyped + + def on_args_add: (*untyped args) -> untyped + + def on_args_add_block: (*untyped args) -> untyped + + def on_args_add_star: (*untyped args) -> untyped + + def on_args_forward: (*untyped args) -> untyped + + def on_args_new: (*untyped args) -> untyped + + def on_array: (*untyped args) -> untyped + + def on_aryptn: (*untyped args) -> untyped + + def on_assign: (*untyped args) -> untyped + + def on_assign_error: (*untyped args) -> untyped + + def on_assoc_new: (*untyped args) -> untyped + + def on_assoc_splat: (*untyped args) -> untyped + + def on_assoclist_from_args: (*untyped args) -> untyped + + def on_backref: (untyped tok) -> untyped + + def on_backtick: (untyped tok) -> untyped + + def on_bare_assoc_hash: (*untyped args) -> untyped + + def on_begin: (*untyped args) -> untyped + + def on_binary: (*untyped args) -> untyped + + def on_block_var: (*untyped args) -> untyped + + def on_blockarg: (*untyped args) -> untyped + + def on_bodystmt: (*untyped args) -> untyped + + def on_brace_block: (*untyped args) -> untyped + + def on_break: (*untyped args) -> untyped + + def on_call: (*untyped args) -> untyped + + def on_case: (*untyped args) -> untyped + + def on_class: (*untyped args) -> untyped + + def on_class_name_error: (*untyped args) -> untyped + + def on_comma: (untyped tok) -> untyped + + def on_command: (*untyped args) -> untyped + + def on_command_call: (*untyped args) -> untyped + + def on_comment: (untyped tok) -> untyped + + def on_const: (untyped tok) -> untyped + + def on_const_path_field: (*untyped args) -> untyped + + def on_const_path_ref: (*untyped args) -> untyped + + def on_const_ref: (*untyped args) -> untyped + + def on_cvar: (untyped tok) -> untyped + + def on_def: (*untyped args) -> untyped + + def on_defined: (*untyped args) -> untyped + + def on_defs: (*untyped args) -> untyped + + def on_do_block: (*untyped args) -> untyped + + def on_dot2: (*untyped args) -> untyped + + def on_dot3: (*untyped args) -> untyped + + def on_dyna_symbol: (*untyped args) -> untyped + + def on_else: (*untyped args) -> untyped + + def on_elsif: (*untyped args) -> untyped + + def on_embdoc: (untyped tok) -> untyped + + def on_embdoc_beg: (untyped tok) -> untyped + + def on_embdoc_end: (untyped tok) -> untyped + + def on_embexpr_beg: (untyped tok) -> untyped + + def on_embexpr_end: (untyped tok) -> untyped + + def on_embvar: (untyped tok) -> untyped + + def on_ensure: (*untyped args) -> untyped + + def on_excessed_comma: (*untyped args) -> untyped + + def on_fcall: (*untyped args) -> untyped + + def on_field: (*untyped args) -> untyped + + def on_float: (untyped tok) -> untyped + + def on_fndptn: (*untyped args) -> untyped + + def on_for: (*untyped args) -> untyped + + def on_gvar: (untyped tok) -> untyped + + def on_hash: (*untyped args) -> untyped + + def on_heredoc_beg: (untyped tok) -> untyped + + def on_heredoc_end: (untyped tok) -> untyped + + def on_hshptn: (*untyped args) -> untyped + + def on_ident: (untyped tok) -> untyped + + def on_if: (*untyped args) -> untyped + + def on_if_mod: (*untyped args) -> untyped + + def on_ifop: (*untyped args) -> untyped + + def on_ignored_nl: (untyped tok) -> untyped + + def on_ignored_sp: (untyped tok) -> untyped + + def on_imaginary: (untyped tok) -> untyped + + def on_in: (*untyped args) -> untyped + + def on_int: (untyped tok) -> untyped + + def on_ivar: (untyped tok) -> untyped + + def on_kw: (untyped tok) -> untyped + + def on_kwrest_param: (*untyped args) -> untyped + + def on_label: (untyped tok) -> untyped + + def on_label_end: (untyped tok) -> untyped + + def on_lambda: (*untyped args) -> untyped + + def on_lbrace: (untyped tok) -> untyped + + def on_lbracket: (untyped tok) -> untyped + + def on_lparen: (untyped tok) -> untyped + + def on_magic_comment: (*untyped args) -> untyped + + def on_massign: (*untyped args) -> untyped + + def on_method_add_arg: (*untyped args) -> untyped + + def on_method_add_block: (*untyped args) -> untyped + + def on_mlhs_add: (*untyped args) -> untyped + + def on_mlhs_add_post: (*untyped args) -> untyped + + def on_mlhs_add_star: (*untyped args) -> untyped + + def on_mlhs_new: (*untyped args) -> untyped + + def on_mlhs_paren: (*untyped args) -> untyped + + def on_module: (*untyped args) -> untyped + + def on_mrhs_add: (*untyped args) -> untyped + + def on_mrhs_add_star: (*untyped args) -> untyped + + def on_mrhs_new: (*untyped args) -> untyped + + def on_mrhs_new_from_args: (*untyped args) -> untyped + + def on_next: (*untyped args) -> untyped + + def on_nl: (untyped tok) -> untyped + + def on_nokw_param: (*untyped args) -> untyped + + def on_op: (untyped tok) -> untyped + + def on_opassign: (*untyped args) -> untyped + + def on_operator_ambiguous: (*untyped args) -> untyped + + def on_param_error: (*untyped args) -> untyped + + def on_params: (*untyped args) -> untyped + + def on_paren: (*untyped args) -> untyped + + alias on_parse_error on_error + def on_period: (untyped tok) -> untyped + + def on_program: (*untyped args) -> untyped + + def on_qsymbols_add: (*untyped args) -> untyped + + def on_qsymbols_beg: (untyped tok) -> untyped + + def on_qsymbols_new: (*untyped args) -> untyped + + def on_qwords_add: (*untyped args) -> untyped + + def on_qwords_beg: (untyped tok) -> untyped + + def on_qwords_new: (*untyped args) -> untyped + + def on_rational: (untyped tok) -> untyped + + def on_rbrace: (untyped tok) -> untyped + + def on_rbracket: (untyped tok) -> untyped + + def on_redo: (*untyped args) -> untyped + + def on_regexp_add: (*untyped args) -> untyped + + def on_regexp_beg: (untyped tok) -> untyped + + def on_regexp_end: (untyped tok) -> untyped + + def on_regexp_literal: (*untyped args) -> untyped + + def on_regexp_new: (*untyped args) -> untyped + + def on_rescue: (*untyped args) -> untyped + + def on_rescue_mod: (*untyped args) -> untyped + + def on_rest_param: (*untyped args) -> untyped + + def on_retry: (*untyped args) -> untyped + + def on_return: (*untyped args) -> untyped + + def on_return0: (*untyped args) -> untyped + + def on_rparen: (untyped tok) -> untyped + + def on_sclass: (*untyped args) -> untyped + + def on_semicolon: (untyped tok) -> untyped + + def on_sp: (untyped tok) -> untyped + + def on_stmts_add: (*untyped args) -> untyped + + def on_stmts_new: (*untyped args) -> untyped + + def on_string_add: (*untyped args) -> untyped + + def on_string_concat: (*untyped args) -> untyped + + def on_string_content: (*untyped args) -> untyped + + def on_string_dvar: (*untyped args) -> untyped + + def on_string_embexpr: (*untyped args) -> untyped + + def on_string_literal: (*untyped args) -> untyped + + def on_super: (*untyped args) -> untyped + + def on_symbeg: (untyped tok) -> untyped + + def on_symbol: (*untyped args) -> untyped + + def on_symbol_literal: (*untyped args) -> untyped + + def on_symbols_add: (*untyped args) -> untyped + + def on_symbols_beg: (untyped tok) -> untyped + + def on_symbols_new: (*untyped args) -> untyped + + def on_tlambda: (untyped tok) -> untyped + + def on_tlambeg: (untyped tok) -> untyped + + def on_top_const_field: (*untyped args) -> untyped + + def on_top_const_ref: (*untyped args) -> untyped + + def on_tstring_beg: (untyped tok) -> untyped + + def on_tstring_content: (untyped tok) -> untyped + + def on_tstring_end: (untyped tok) -> untyped + + def on_unary: (*untyped args) -> untyped + + def on_undef: (*untyped args) -> untyped + + def on_unless: (*untyped args) -> untyped + + def on_unless_mod: (*untyped args) -> untyped + + def on_until: (*untyped args) -> untyped + + def on_until_mod: (*untyped args) -> untyped + + def on_var_alias: (*untyped args) -> untyped + + def on_var_field: (*untyped args) -> untyped + + def on_var_ref: (*untyped args) -> untyped + + def on_vcall: (*untyped args) -> untyped + + def on_void_stmt: (*untyped args) -> untyped + + def on_when: (*untyped args) -> untyped + + def on_while: (*untyped args) -> untyped + + def on_while_mod: (*untyped args) -> untyped + + def on_word_add: (*untyped args) -> untyped + + def on_word_new: (*untyped args) -> untyped + + def on_words_add: (*untyped args) -> untyped + + def on_words_beg: (untyped tok) -> untyped + + def on_words_new: (*untyped args) -> untyped + + def on_words_sep: (untyped tok) -> untyped + + def on_xstring_add: (*untyped args) -> untyped + + def on_xstring_literal: (*untyped args) -> untyped + + def on_xstring_new: (*untyped args) -> untyped + + def on_yield: (*untyped args) -> untyped + + def on_yield0: (*untyped args) -> untyped + + def on_zsuper: (*untyped args) -> untyped + + private + + def dedent_element: (untyped e, untyped width) -> untyped + + def on_error: (untyped mesg) -> untyped + + def on_heredoc_dedent: (untyped val, untyped width) -> untyped + end + + class SexpBuilderPP < Ripper::SexpBuilder + alias on_args_add _dispatch_event_push + + alias on_args_new _dispatch_event_new + + alias on_mlhs_add _dispatch_event_push + + alias on_mlhs_new _dispatch_event_new + + alias on_mrhs_add _dispatch_event_push + + alias on_mrhs_new _dispatch_event_new + + alias on_qsymbols_add _dispatch_event_push + + alias on_qsymbols_new _dispatch_event_new + + alias on_qwords_add _dispatch_event_push + + alias on_qwords_new _dispatch_event_new + + alias on_regexp_add _dispatch_event_push + + alias on_regexp_new _dispatch_event_new + + alias on_stmts_add _dispatch_event_push + + alias on_stmts_new _dispatch_event_new + + alias on_string_add _dispatch_event_push + + alias on_symbols_add _dispatch_event_push + + alias on_symbols_new _dispatch_event_new + + alias on_word_add _dispatch_event_push + + alias on_word_new _dispatch_event_new + + alias on_words_add _dispatch_event_push + + alias on_words_new _dispatch_event_new + + alias on_xstring_add _dispatch_event_push + + alias on_xstring_new _dispatch_event_new + + private + + def _dispatch_event_new: () -> untyped + + def _dispatch_event_push: (untyped list, untyped item) -> untyped + + def on_heredoc_dedent: (untyped val, untyped width) -> untyped + + def on_mlhs_add_post: (untyped list, untyped post) -> untyped + + def on_mlhs_add_star: (untyped list, untyped star) -> untyped + + def on_mlhs_paren: (untyped list) -> untyped + end + + class TokenPattern + MAP: Hash[String, String] + + class CompileError < Error + end + class Error < StandardError + end + + class MatchData + private + + def initialize: (untyped tokens, untyped match) -> void + + public + + def string: (?untyped n) -> untyped + + private + + def match: (?untyped n) -> untyped + end + class MatchError < Error + end + alias self.compile self.new + + private + + def initialize: (untyped pattern) -> void + + public + + def match: (untyped str) -> untyped + + def match_list: (untyped tokens) -> untyped + + private + + def compile: (untyped pattern) -> untyped + + def map_token: (untyped tok) -> untyped + + def map_tokens: (untyped tokens) -> untyped + end + interface _Gets + def gets: (?String sep, ?Integer limit) -> String? + end + + # + # USE OF RIPPER LIBRARY ONLY. + # + # Strips up to `width` leading whitespaces from `input`, and returns the + # stripped column width. + # + def self.dedent_string: (String input, int width) -> Integer + + # + # Tokenizes the Ruby program and returns an array of an array, which is + # formatted like `[[lineno, column], type, token, state]`. The `filename` + # argument is mostly ignored. By default, this method does not handle syntax + # errors in `src`, use the `raise_errors` keyword to raise a SyntaxError for an + # error in `src`. + # + # require 'ripper' + # require 'pp' + # + # pp Ripper.lex("def m(a) nil end") + # #=> [[[1, 0], :on_kw, "def", FNAME ], + # [[1, 3], :on_sp, " ", FNAME ], + # [[1, 4], :on_ident, "m", ENDFN ], + # [[1, 5], :on_lparen, "(", BEG|LABEL], + # [[1, 6], :on_ident, "a", ARG ], + # [[1, 7], :on_rparen, ")", ENDFN ], + # [[1, 8], :on_sp, " ", BEG ], + # [[1, 9], :on_kw, "nil", END ], + # [[1, 12], :on_sp, " ", END ], + # [[1, 13], :on_kw, "end", END ]] + # + def self.lex: (String src, ?String filename, ?Integer lineno, ?raise_errors: boolish) -> Array[[ [ Integer, Integer ], Symbol, String, Lexer::State ]] + + # + # Returns a string representation of lex_state. + # + def self.lex_state_name: (int) -> String + + # + # Parses the given Ruby program read from `src`. `src` must be a String or an IO + # or a object with a #gets method. + # + def self.parse: (File | _Gets | String src, ?String filename, ?Integer lineno) -> nil + + # + # EXPERIMENTAL + # : Parses `src` and create S-exp tree. Returns more readable tree rather than + # Ripper.sexp_raw. This method is mainly for developer use. The `filename` + # argument is mostly ignored. By default, this method does not handle syntax + # errors in `src`, returning `nil` in such cases. Use the `raise_errors` + # keyword to raise a SyntaxError for an error in `src`. + # + # require 'ripper' + # require 'pp' + # + # pp Ripper.sexp("def m(a) nil end") + # #=> [:program, + # [[:def, + # [:@ident, "m", [1, 4]], + # [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil, nil, nil, nil]], + # [:bodystmt, [[:var_ref, [:@kw, "nil", [1, 9]]]], nil, nil, nil]]]] + # + def self.sexp: (File | _Gets | String src, ?String filename, ?Integer lineno, ?raise_errors: boolish) -> Array[untyped] + + # + # EXPERIMENTAL + # : Parses `src` and create S-exp tree. This method is mainly for developer + # use. The `filename` argument is mostly ignored. By default, this method + # does not handle syntax errors in `src`, returning `nil` in such cases. Use + # the `raise_errors` keyword to raise a SyntaxError for an error in `src`. + # + # require 'ripper' + # require 'pp' + # + # pp Ripper.sexp_raw("def m(a) nil end") + # #=> [:program, + # [:stmts_add, + # [:stmts_new], + # [:def, + # [:@ident, "m", [1, 4]], + # [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil]], + # [:bodystmt, + # [:stmts_add, [:stmts_new], [:var_ref, [:@kw, "nil", [1, 9]]]], + # nil, + # nil, + # nil]]]] + # + def self.sexp_raw: (File | _Gets | String src, ?String filename, ?Integer lineno, ?raise_errors: boolish) -> Array[untyped] + + # + # EXPERIMENTAL + # : Parses `src` and return a string which was matched to `pattern`. `pattern` + # should be described as Regexp. + # + # require 'ripper' + # + # p Ripper.slice('def m(a) nil end', 'ident') #=> "m" + # p Ripper.slice('def m(a) nil end', '[ident lparen rparen]+') #=> "m(a)" + # p Ripper.slice("< "string\n" + # + def self.slice: (String src, String pattern, ?Integer n) -> String? + + def self.token_match: (String src, String pattern) -> Ripper::TokenPattern::MatchData? + + # + # Tokenizes the Ruby program and returns an array of strings. The `filename` and + # `lineno` arguments are mostly ignored, since the return value is just the + # tokenized input. By default, this method does not handle syntax errors in + # `src`, use the `raise_errors` keyword to raise a SyntaxError for an error in + # `src`. + # + # p Ripper.tokenize("def m(a) nil end") + # # => ["def", " ", "m", "(", "a", ")", " ", "nil", " ", "end"] + # + def self.tokenize: (File | _Gets | String src, ?String filename, ?Integer lineno, ?raise_errors: boolish) -> Array[String] + + private + + # + # Create a new Ripper object. *src* must be a String, an IO, or an Object which + # has #gets method. + # + # This method does not starts parsing. See also Ripper#parse and Ripper.parse. + # + def initialize: (File | _Gets | String src, ?String filename, ?Integer lineno) -> void + + public + + # + # Return column number of current parsing line. This number starts from 0. + # + def column: () -> Integer? + + # + # Get debug output. + # + def debug_output: () -> untyped + + # + # Set debug output. + # + def debug_output=: (untyped) -> untyped + + # + # Return encoding of the source. + # + def encoding: () -> Encoding + + # + # Return true if parsed source ended by +_*END*_+. + # + def end_seen?: () -> bool + + # + # Return true if parsed source has errors. + # + def error?: () -> bool + + # + # Return current parsing filename. + # + def filename: () -> String + + # + # Return line number of current parsing line. This number starts from 1. + # + def lineno: () -> Integer? + + alias on_BEGIN _dispatch_1 + + alias on_CHAR _dispatch_1 + + alias on_END _dispatch_1 + + alias on___end__ _dispatch_1 + + alias on_alias _dispatch_2 + + alias on_alias_error _dispatch_2 + + alias on_aref _dispatch_2 + + alias on_aref_field _dispatch_2 + + alias on_arg_ambiguous _dispatch_1 + + alias on_arg_paren _dispatch_1 + + alias on_args_add _dispatch_2 + + alias on_args_add_block _dispatch_2 + + alias on_args_add_star _dispatch_2 + + alias on_args_forward _dispatch_0 + + alias on_args_new _dispatch_0 + + alias on_array _dispatch_1 + + alias on_aryptn _dispatch_4 + + alias on_assign _dispatch_2 + + alias on_assign_error _dispatch_2 + + alias on_assoc_new _dispatch_2 + + alias on_assoc_splat _dispatch_1 + + alias on_assoclist_from_args _dispatch_1 + + alias on_backref _dispatch_1 + + alias on_backtick _dispatch_1 + + alias on_bare_assoc_hash _dispatch_1 + + alias on_begin _dispatch_1 + + alias on_binary _dispatch_3 + + alias on_block_var _dispatch_2 + + alias on_blockarg _dispatch_1 + + alias on_bodystmt _dispatch_4 + + alias on_brace_block _dispatch_2 + + alias on_break _dispatch_1 + + alias on_call _dispatch_3 + + alias on_case _dispatch_2 + + alias on_class _dispatch_3 + + alias on_class_name_error _dispatch_2 + + alias on_comma _dispatch_1 + + alias on_command _dispatch_2 + + alias on_command_call _dispatch_4 + + alias on_comment _dispatch_1 + + alias on_const _dispatch_1 + + alias on_const_path_field _dispatch_2 + + alias on_const_path_ref _dispatch_2 + + alias on_const_ref _dispatch_1 + + alias on_cvar _dispatch_1 + + alias on_def _dispatch_3 + + alias on_defined _dispatch_1 + + alias on_defs _dispatch_5 + + alias on_do_block _dispatch_2 + + alias on_dot2 _dispatch_2 + + alias on_dot3 _dispatch_2 + + alias on_dyna_symbol _dispatch_1 + + alias on_else _dispatch_1 + + alias on_elsif _dispatch_3 + + alias on_embdoc _dispatch_1 + + alias on_embdoc_beg _dispatch_1 + + alias on_embdoc_end _dispatch_1 + + alias on_embexpr_beg _dispatch_1 + + alias on_embexpr_end _dispatch_1 + + alias on_embvar _dispatch_1 + + alias on_ensure _dispatch_1 + + alias on_excessed_comma _dispatch_0 + + alias on_fcall _dispatch_1 + + alias on_field _dispatch_3 + + alias on_float _dispatch_1 + + alias on_fndptn _dispatch_4 + + alias on_for _dispatch_3 + + alias on_gvar _dispatch_1 + + alias on_hash _dispatch_1 + + alias on_heredoc_beg _dispatch_1 + + alias on_heredoc_dedent _dispatch_2 + + alias on_heredoc_end _dispatch_1 + + alias on_hshptn _dispatch_3 + + alias on_ident _dispatch_1 + + alias on_if _dispatch_3 + + alias on_if_mod _dispatch_2 + + alias on_ifop _dispatch_3 + + alias on_ignored_nl _dispatch_1 + + alias on_imaginary _dispatch_1 + + alias on_in _dispatch_3 + + alias on_int _dispatch_1 + + alias on_ivar _dispatch_1 + + alias on_kw _dispatch_1 + + alias on_kwrest_param _dispatch_1 + + alias on_label _dispatch_1 + + alias on_label_end _dispatch_1 + + alias on_lambda _dispatch_2 + + alias on_lbrace _dispatch_1 + + alias on_lbracket _dispatch_1 + + alias on_lparen _dispatch_1 + + alias on_magic_comment _dispatch_2 + + alias on_massign _dispatch_2 + + alias on_method_add_arg _dispatch_2 + + alias on_method_add_block _dispatch_2 + + alias on_mlhs_add _dispatch_2 + + alias on_mlhs_add_post _dispatch_2 + + alias on_mlhs_add_star _dispatch_2 + + alias on_mlhs_new _dispatch_0 + + alias on_mlhs_paren _dispatch_1 + + alias on_module _dispatch_2 + + alias on_mrhs_add _dispatch_2 + + alias on_mrhs_add_star _dispatch_2 + + alias on_mrhs_new _dispatch_0 + + alias on_mrhs_new_from_args _dispatch_1 + + alias on_next _dispatch_1 + + alias on_nl _dispatch_1 + + alias on_nokw_param _dispatch_1 + + alias on_op _dispatch_1 + + alias on_opassign _dispatch_3 + + alias on_operator_ambiguous _dispatch_2 + + alias on_param_error _dispatch_2 + + alias on_params _dispatch_7 + + alias on_paren _dispatch_1 + + alias on_parse_error _dispatch_1 + + alias on_period _dispatch_1 + + alias on_program _dispatch_1 + + alias on_qsymbols_add _dispatch_2 + + alias on_qsymbols_beg _dispatch_1 + + alias on_qsymbols_new _dispatch_0 + + alias on_qwords_add _dispatch_2 + + alias on_qwords_beg _dispatch_1 + + alias on_qwords_new _dispatch_0 + + alias on_rational _dispatch_1 + + alias on_rbrace _dispatch_1 + + alias on_rbracket _dispatch_1 + + alias on_redo _dispatch_0 + + alias on_regexp_add _dispatch_2 + + alias on_regexp_beg _dispatch_1 + + alias on_regexp_end _dispatch_1 + + alias on_regexp_literal _dispatch_2 + + alias on_regexp_new _dispatch_0 + + alias on_rescue _dispatch_4 + + alias on_rescue_mod _dispatch_2 + + alias on_rest_param _dispatch_1 + + alias on_retry _dispatch_0 + + alias on_return _dispatch_1 + + alias on_return0 _dispatch_0 + + alias on_rparen _dispatch_1 + + alias on_sclass _dispatch_2 + + alias on_semicolon _dispatch_1 + + alias on_sp _dispatch_1 + + alias on_stmts_add _dispatch_2 + + alias on_stmts_new _dispatch_0 + + alias on_string_add _dispatch_2 + + alias on_string_concat _dispatch_2 + + alias on_string_content _dispatch_0 + + alias on_string_dvar _dispatch_1 + + alias on_string_embexpr _dispatch_1 + + alias on_string_literal _dispatch_1 + + alias on_super _dispatch_1 + + alias on_symbeg _dispatch_1 + + alias on_symbol _dispatch_1 + + alias on_symbol_literal _dispatch_1 + + alias on_symbols_add _dispatch_2 + + alias on_symbols_beg _dispatch_1 + + alias on_symbols_new _dispatch_0 + + alias on_tlambda _dispatch_1 + + alias on_tlambeg _dispatch_1 + + alias on_top_const_field _dispatch_1 + + alias on_top_const_ref _dispatch_1 + + alias on_tstring_beg _dispatch_1 + + alias on_tstring_content _dispatch_1 + + alias on_tstring_end _dispatch_1 + + alias on_unary _dispatch_2 + + alias on_undef _dispatch_1 + + alias on_unless _dispatch_3 + + alias on_unless_mod _dispatch_2 + + alias on_until _dispatch_2 + + alias on_until_mod _dispatch_2 + + alias on_var_alias _dispatch_2 + + alias on_var_field _dispatch_1 + + alias on_var_ref _dispatch_1 + + alias on_vcall _dispatch_1 + + alias on_void_stmt _dispatch_0 + + alias on_when _dispatch_3 + + alias on_while _dispatch_2 + + alias on_while_mod _dispatch_2 + + alias on_word_add _dispatch_2 + + alias on_word_new _dispatch_0 + + alias on_words_add _dispatch_2 + + alias on_words_beg _dispatch_1 + + alias on_words_new _dispatch_0 + + alias on_words_sep _dispatch_1 + + alias on_xstring_add _dispatch_2 + + alias on_xstring_literal _dispatch_1 + + alias on_xstring_new _dispatch_0 + + alias on_yield _dispatch_1 + + alias on_yield0 _dispatch_0 + + alias on_zsuper _dispatch_0 + + # + # Start parsing and returns the value of the root action. + # + def parse: () -> nil + + # + # Return scanner state of current token. + # + def state: () -> Integer? + + # + # Return the current token string. + # + def token: () -> String? + + # + # Get yydebug. + # + def yydebug: () -> bool + + # + # Set yydebug. + # + def yydebug=: (bool) -> bool + + private + + def _dispatch_0: () -> void + + def _dispatch_1: (untyped a) -> void + + def _dispatch_2: (untyped a, untyped b) -> void + + def _dispatch_3: (untyped a, untyped b, untyped c) -> void + + def _dispatch_4: (untyped a, untyped b, untyped c, untyped d) -> void + + def _dispatch_5: (untyped a, untyped b, untyped c, untyped d, untyped e) -> void + + def _dispatch_6: (untyped a, untyped b, untyped c, untyped d, untyped e, untyped f) -> void + + def _dispatch_7: (untyped a, untyped b, untyped c, untyped d, untyped e, untyped f, untyped g) -> void + + # + # This method is called when the parser found syntax error. + # + def compile_error: (untyped msg) -> untyped + + # + # USE OF RIPPER LIBRARY ONLY. + # + # Strips up to `width` leading whitespaces from `input`, and returns the + # stripped column width. + # + def dedent_string: (String input, Integer width) -> Integer + + # + # This method is called when weak warning is produced by the parser. `fmt` and + # `args` is printf style. + # + def warn: (untyped fmt, *untyped args) -> untyped + + # + # This method is called when strong warning is produced by the parser. `fmt` and + # `args` is printf style. + # + def warning: (untyped fmt, *untyped args) -> untyped +end diff --git a/test/stdlib/Ripper_test.rb b/test/stdlib/Ripper_test.rb new file mode 100644 index 000000000..e5d4c1b6c --- /dev/null +++ b/test/stdlib/Ripper_test.rb @@ -0,0 +1,234 @@ +require_relative "test_helper" + +class RipperSingletonTest < Test::Unit::TestCase + include TypeAssertions + + library "ripper" + testing "singleton(::Ripper)" + + def test_new + assert_send_type "(::File | ::Ripper::_Gets | ::String src, ?::String filename, ?::Integer lineno) -> ::Ripper", + Ripper, :new, "def a; end" + end + + def test_dedent_string + assert_send_type "(::String input, ::int width) -> ::Integer", + Ripper, :dedent_string, "", 0 + end + + def test_lex + assert_send_type "(::String src, ?::String filename, ?::Integer lineno, ?raise_errors: ::boolish) -> ::Array[[ [ ::Integer, ::Integer ], ::Symbol, ::String, ::Ripper::Lexer::State ]]", + Ripper, :lex, "def a; end" + end + + def test_lex_state_name + assert_send_type "(::int) -> ::String", + Ripper, :lex_state_name, 1 + end + + def test_parse + assert_send_type "(::File | ::Ripper::_Gets | ::String src, ?::String filename, ?::Integer lineno) -> nil", + Ripper, :parse, "def a; end" + end + + def test_sexp + assert_send_type "(::File | ::Ripper::_Gets | ::String src, ?::String filename, ?::Integer lineno, ?raise_errors: ::boolish) -> ::Array[untyped]", + Ripper, :sexp, "def a; end" + end + + def test_sexp_raw + assert_send_type "(::File | ::Ripper::_Gets | ::String src, ?::String filename, ?::Integer lineno, ?raise_errors: ::boolish) -> ::Array[untyped]", + Ripper, :sexp_raw, "def a; end" + end + + def test_slice + assert_send_type "(::String src, ::String pattern, ?::Integer n) -> ::String?", + Ripper, :slice, "def a; end", "" + end + + def test_token_match + assert_send_type "(::String src, ::String pattern) -> ::Ripper::TokenPattern::MatchData?", + Ripper, :token_match, "def a; end", "" + end + + def test_tokenize + assert_send_type "(::File | ::Ripper::_Gets | ::String src, ?::String filename, ?::Integer lineno, ?raise_errors: ::boolish) -> ::Array[::String]", + Ripper, :tokenize, "def a; end" + end +end + +class RipperTest < Test::Unit::TestCase + include TypeAssertions + + library "ripper" + testing "::Ripper" + + def test_warn + assert_send_type "(untyped fmt, *untyped args) -> untyped", + Ripper.new("def a; end"), :warn, "" + end + + def test_column + assert_send_type "() -> ::Integer?", + Ripper.new("def a; end"), :column + end + + def test_debug_output + assert_send_type "() -> untyped", + Ripper.new("def a; end"), :debug_output + end + + def test_debug_output= + assert_send_type "(untyped) -> untyped", + Ripper.new("def a; end"), :debug_output=, true + end + + def test_encoding + assert_send_type "() -> ::Encoding", + Ripper.new("def a; end"), :encoding + end + + def test_end_seen? + assert_send_type "() -> bool", + Ripper.new("def a; end"), :end_seen? + end + + def test_error? + assert_send_type "() -> bool", + Ripper.new("def a; end"), :error? + end + + def test_filename + assert_send_type "() -> ::String", + Ripper.new("def a; end"), :filename + end + + def test_lineno + assert_send_type "() -> ::Integer?", + Ripper.new("def a; end"), :lineno + end + + def test__dispatch_0 + assert_send_type "() -> void", + Ripper.new("def a; end"), :_dispatch_0 + end + + def test__dispatch_1 + assert_send_type "(untyped a) -> void", + Ripper.new("def a; end"), :_dispatch_1, "" + end + + def test__dispatch_2 + assert_send_type "(untyped a, untyped b) -> void", + Ripper.new("def a; end"), :_dispatch_2, "", "" + end + + def test__dispatch_3 + assert_send_type "(untyped a, untyped b, untyped c) -> void", + Ripper.new("def a; end"), :_dispatch_3, "", "", "" + end + + def test__dispatch_4 + assert_send_type "(untyped a, untyped b, untyped c, untyped d) -> void", + Ripper.new("def a; end"), :_dispatch_4, "", "", "", "" + end + + def test__dispatch_5 + assert_send_type "(untyped a, untyped b, untyped c, untyped d, untyped e) -> void", + Ripper.new("def a; end"), :_dispatch_5, "", "", "", "", "" + end + + def test__dispatch_6 + assert_send_type "(untyped a, untyped b, untyped c, untyped d, untyped e, untyped f) -> void", + Ripper.new("def a; end"), :_dispatch_6, "", "", "", "", "", "" + end + + def test__dispatch_7 + assert_send_type "(untyped a, untyped b, untyped c, untyped d, untyped e, untyped f, untyped g) -> void", + Ripper.new("def a; end"), :_dispatch_7, "", "", "", "", "", "", "" + end + + def test_parse + assert_send_type "() -> nil", + Ripper.new("def a; end"), :parse + end + + def test_state + assert_send_type "() -> ::Integer?", + Ripper.new("def a; end"), :state + end + + def test_token + assert_send_type "() -> ::String?", + Ripper.new("def a; end"), :token + end + + def test_yydebug + assert_send_type "() -> bool", + Ripper.new("def a; end"), :yydebug + end + + def test_yydebug= + assert_send_type "(bool) -> bool", + Ripper.new("def a; end"), :yydebug=, true + end + + def test_compile_error + assert_send_type "(untyped msg) -> untyped", + Ripper.new("def a; end"), :compile_error, "" + end + + def test_dedent_string + assert_send_type "(String input, Integer width) -> Integer", + Ripper.new("def a; end"), :dedent_string, "", 0 + end + + def test_warning + assert_send_type "(untyped fmt, *untyped args) -> untyped", + Ripper.new("def a; end"), :warning, "" + end +end + +class Ripper::FilterSingletonTest < Test::Unit::TestCase + include TypeAssertions + + library "ripper" + testing "singleton(::Ripper::Filter)" + + def test_new + assert_send_type "(::File | ::Ripper::_Gets | ::String src, ?::String filename, ?::Integer lineno) -> ::Ripper::Filter", + Ripper::Filter, :new, "def a; end" + end +end + +class Ripper::FilterTest < Test::Unit::TestCase + include TypeAssertions + + library "ripper" + testing "::Ripper::Filter" + + def test_column + assert_send_type "() -> ::Integer?", + Ripper::Filter.new("def a; end"), :column + end + + def test_filename + assert_send_type "() -> ::String", + Ripper::Filter.new("def a; end").tap(&:parse), :filename + end + + def test_lineno + assert_send_type "() -> ::Integer?", + Ripper::Filter.new("def a; end").tap(&:parse), :lineno + end + + def test_parse + assert_send_type "(?untyped init) -> untyped", + Ripper::Filter.new("def a; end"), :parse + end + + def test_state + assert_send_type "() -> untyped", + Ripper::Filter.new("def a; end").tap(&:parse), :state + end +end