docspring 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/Gemfile.lock +4 -4
- data/README.md +11 -5
- data/docs/CreateHtmlSubmissionData.md +3 -1
- data/docs/CreatePdfSubmissionData.md +3 -1
- data/docs/PDFApi.md +156 -10
- data/docs/PublishVersionData.md +20 -0
- data/docs/RestoreVersionData.md +18 -0
- data/docs/Submission.md +4 -0
- data/docs/SubmissionPreview.md +4 -0
- data/docs/Template.md +15 -1
- data/docs/TemplateDeleteResponse.md +24 -0
- data/docs/TemplatePreview.md +13 -1
- data/docs/TemplatePublishVersionResponse.md +22 -0
- data/lib/docspring/api/pdf_api.rb +152 -5
- data/lib/docspring/api_client.rb +1 -1
- data/lib/docspring/models/combined_submission_action.rb +1 -5
- data/lib/docspring/models/create_html_submission_data.rb +13 -4
- data/lib/docspring/models/create_pdf_submission_data.rb +13 -4
- data/lib/docspring/models/publish_version_data.rb +230 -0
- data/lib/docspring/models/restore_version_data.rb +221 -0
- data/lib/docspring/models/submission.rb +41 -1
- data/lib/docspring/models/submission_data_request_event.rb +1 -5
- data/lib/docspring/models/submission_preview.rb +41 -1
- data/lib/docspring/models/template.rb +106 -4
- data/lib/docspring/models/template_delete_response.rb +287 -0
- data/lib/docspring/models/template_preview.rb +88 -4
- data/lib/docspring/models/template_publish_version_response.rb +282 -0
- data/lib/docspring/version.rb +1 -1
- data/lib/docspring.rb +4 -0
- data/spec/api/pdf_api_spec.rb +27 -2
- data/spec/models/create_html_submission_data_spec.rb +6 -0
- data/spec/models/create_pdf_submission_data_spec.rb +6 -0
- data/spec/models/publish_version_data_spec.rb +42 -0
- data/spec/models/restore_version_data_spec.rb +36 -0
- data/spec/models/submission_preview_spec.rb +16 -0
- data/spec/models/submission_spec.rb +16 -0
- data/spec/models/template_delete_response_spec.rb +58 -0
- data/spec/models/template_preview_spec.rb +40 -0
- data/spec/models/template_publish_version_response_spec.rb +52 -0
- data/spec/models/template_spec.rb +46 -0
- data/vendor/bundle/ruby/3.3.0/bin/irb +29 -0
- data/vendor/bundle/ruby/3.3.0/bin/rdbg +29 -0
- data/vendor/bundle/ruby/3.3.0/bin/rdoc +29 -0
- data/vendor/bundle/ruby/3.3.0/bin/ri +29 -0
- data/vendor/bundle/ruby/3.3.0/cache/ast-2.4.3.gem +0 -0
- data/vendor/bundle/ruby/3.3.0/cache/debug-1.10.0.gem +0 -0
- data/vendor/bundle/ruby/3.3.0/cache/io-console-0.8.0.gem +0 -0
- data/vendor/bundle/ruby/3.3.0/cache/irb-1.15.1.gem +0 -0
- data/vendor/bundle/ruby/3.3.0/cache/parser-3.3.7.2.gem +0 -0
- data/vendor/bundle/ruby/3.3.0/cache/pp-0.6.2.gem +0 -0
- data/vendor/bundle/ruby/3.3.0/cache/prettyprint-0.2.0.gem +0 -0
- data/vendor/bundle/ruby/3.3.0/cache/rdoc-6.12.0.gem +0 -0
- data/vendor/bundle/ruby/3.3.0/cache/reline-0.6.0.gem +0 -0
- data/vendor/bundle/ruby/3.3.0/extensions/arm64-darwin-24/3.3.0/debug-1.10.0/debug/debug.bundle +0 -0
- data/vendor/bundle/ruby/3.3.0/extensions/arm64-darwin-24/3.3.0/debug-1.10.0/gem.build_complete +0 -0
- data/vendor/bundle/ruby/3.3.0/extensions/arm64-darwin-24/3.3.0/debug-1.10.0/gem_make.out +19 -0
- data/vendor/bundle/ruby/3.3.0/extensions/arm64-darwin-24/3.3.0/io-console-0.8.0/gem.build_complete +0 -0
- data/vendor/bundle/ruby/3.3.0/extensions/arm64-darwin-24/3.3.0/io-console-0.8.0/gem_make.out +31 -0
- data/vendor/bundle/ruby/3.3.0/extensions/arm64-darwin-24/3.3.0/io-console-0.8.0/io/console.bundle +0 -0
- data/vendor/bundle/ruby/3.3.0/extensions/arm64-darwin-24/3.3.0/io-console-0.8.0/mkmf.log +447 -0
- data/vendor/bundle/ruby/3.3.0/gems/ast-2.4.3/LICENSE.MIT +20 -0
- data/vendor/bundle/ruby/3.3.0/gems/ast-2.4.3/README.YARD.md +12 -0
- data/vendor/bundle/ruby/3.3.0/gems/ast-2.4.3/lib/ast/node.rb +268 -0
- data/vendor/bundle/ruby/3.3.0/gems/ast-2.4.3/lib/ast/processor/mixin.rb +288 -0
- data/vendor/bundle/ruby/3.3.0/gems/ast-2.4.3/lib/ast/processor.rb +12 -0
- data/vendor/bundle/ruby/3.3.0/gems/ast-2.4.3/lib/ast/sexp.rb +30 -0
- data/vendor/bundle/ruby/3.3.0/gems/ast-2.4.3/lib/ast.rb +17 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/CONTRIBUTING.md +573 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/Gemfile +10 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/LICENSE.txt +22 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/README.md +970 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/Rakefile +57 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/TODO.md +23 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/debug.gemspec +33 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/exe/rdbg +53 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/ext/debug/Makefile +270 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/ext/debug/debug.c +228 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/ext/debug/debug_version.h +1 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/ext/debug/extconf.rb +27 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/ext/debug/iseq_collector.c +93 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/abbrev_command.rb +77 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/breakpoint.rb +556 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/client.rb +263 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/color.rb +123 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/config.rb +590 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/console.rb +213 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/dap_custom/traceInspector.rb +336 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/debug.bundle +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/frame_info.rb +188 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/irb_integration.rb +37 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/local.rb +115 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/open.rb +13 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/open_nonstop.rb +15 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/prelude.rb +50 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/server.rb +534 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/server_cdp.rb +1348 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/server_dap.rb +1108 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/session.rb +2659 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/source_repository.rb +150 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/start.rb +5 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/thread_client.rb +1455 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/tracer.rb +241 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug/version.rb +5 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/lib/debug.rb +9 -0
- data/vendor/bundle/ruby/3.3.0/gems/debug-1.10.0/misc/README.md.erb +636 -0
- data/vendor/bundle/ruby/3.3.0/gems/io-console-0.8.0/.document +5 -0
- data/vendor/bundle/ruby/3.3.0/gems/io-console-0.8.0/BSDL +22 -0
- data/vendor/bundle/ruby/3.3.0/gems/io-console-0.8.0/COPYING +56 -0
- data/vendor/bundle/ruby/3.3.0/gems/io-console-0.8.0/README.md +46 -0
- data/vendor/bundle/ruby/3.3.0/gems/io-console-0.8.0/ext/io/console/Makefile +272 -0
- data/vendor/bundle/ruby/3.3.0/gems/io-console-0.8.0/ext/io/console/console.c +1969 -0
- data/vendor/bundle/ruby/3.3.0/gems/io-console-0.8.0/ext/io/console/extconf.rb +61 -0
- data/vendor/bundle/ruby/3.3.0/gems/io-console-0.8.0/ext/io/console/win32_vk.inc +1390 -0
- data/vendor/bundle/ruby/3.3.0/gems/io-console-0.8.0/lib/io/console/size.rb +23 -0
- data/vendor/bundle/ruby/3.3.0/gems/io-console-0.8.0/lib/io/console.bundle +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/Gemfile +29 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/LICENSE.txt +22 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/README.md +125 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/Rakefile +52 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/bin/console +6 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/bin/setup +6 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/doc/irb/irb-tools.rd.ja +184 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/doc/irb/irb.rd.ja +425 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/exe/irb +9 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/irb.gemspec +46 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/cmd/nop.rb +4 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/color.rb +263 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/color_printer.rb +56 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/backtrace.rb +17 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/base.rb +60 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/break.rb +17 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/catch.rb +17 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/cd.rb +51 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/chws.rb +40 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/context.rb +16 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/continue.rb +17 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/copy.rb +73 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/debug.rb +73 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/delete.rb +17 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/disable_irb.rb +19 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/edit.rb +63 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/exit.rb +18 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/finish.rb +17 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/force_exit.rb +18 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/help.rb +83 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/history.rb +45 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/info.rb +17 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/internal_helpers.rb +27 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/irb_info.rb +33 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/load.rb +91 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/ls.rb +167 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/measure.rb +49 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/next.rb +17 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/pushws.rb +65 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/show_doc.rb +51 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/show_source.rb +74 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/step.rb +17 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/subirb.rb +123 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command/whereami.rb +23 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/command.rb +23 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/completion.rb +504 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/context.rb +751 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/debug/ui.rb +101 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/debug.rb +127 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/default_commands.rb +279 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/easter-egg.rb +152 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/ext/change-ws.rb +37 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/ext/eval_history.rb +149 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/ext/loader.rb +127 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/ext/multi-irb.rb +258 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/ext/tracer.rb +39 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/ext/use-loader.rb +67 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/ext/workspaces.rb +36 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/frame.rb +80 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/help.rb +28 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/helper_method/base.rb +16 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/helper_method/conf.rb +11 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/helper_method.rb +29 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/history.rb +116 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/init.rb +540 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/input-method.rb +515 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/inspector.rb +136 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/lc/error.rb +52 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/lc/help-message +55 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/lc/ja/error.rb +53 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/lc/ja/help-message +58 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/locale.rb +153 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/nesting_parser.rb +239 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/notifier.rb +230 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/output-method.rb +80 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/pager.rb +213 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/ruby-lex.rb +476 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/ruby_logo.aa +118 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/source_finder.rb +138 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/statement.rb +101 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/version.rb +11 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/workspace.rb +171 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/ws-for-case-2.rb +9 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb/xmp.rb +164 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/lib/irb.rb +736 -0
- data/vendor/bundle/ruby/3.3.0/gems/irb-1.15.1/man/irb.1 +292 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/LICENSE.txt +26 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/bin/ruby-parse +7 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/bin/ruby-rewrite +7 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/gauntlet_parser.rb +123 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/all.rb +17 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/ast/node.rb +40 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/ast/processor.rb +293 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/base.rb +291 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/builders/default.rb +2338 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/clobbering_error.rb +13 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/color.rb +32 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/context.rb +51 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/current.rb +137 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/current_arg_stack.rb +46 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/deprecation.rb +13 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/diagnostic/engine.rb +104 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/diagnostic.rb +163 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/lexer/dedenter.rb +88 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/lexer/explanation.rb +55 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/lexer/literal.rb +284 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/lexer/stack_state.rb +49 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/lexer-F0.rb +12922 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/lexer-F1.rb +14875 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/lexer-strings.rb +5424 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/macruby.rb +9634 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/max_numparam_stack.rb +56 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/messages.rb +125 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/meta.rb +48 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/rewriter.rb +105 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/ruby18.rb +9272 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/ruby19.rb +9558 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/ruby20.rb +10229 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/ruby21.rb +10203 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/ruby22.rb +10302 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/ruby23.rb +10322 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/ruby24.rb +10454 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/ruby25.rb +10374 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/ruby26.rb +10352 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/ruby27.rb +11947 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/ruby30.rb +12243 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/ruby31.rb +12716 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/ruby32.rb +12704 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/ruby33.rb +12589 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/ruby34.rb +12596 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/rubymotion.rb +9515 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/runner/ruby_parse.rb +157 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/runner/ruby_rewrite.rb +101 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/runner.rb +299 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/buffer.rb +369 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/comment/associator.rb +233 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/comment.rb +134 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/map/collection.rb +18 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/map/condition.rb +21 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/map/constant.rb +32 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/map/definition.rb +23 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/map/for.rb +19 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/map/heredoc.rb +19 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/map/index.rb +33 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/map/keyword.rb +20 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/map/method_definition.rb +25 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/map/objc_kwarg.rb +19 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/map/operator.rb +17 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/map/rescue_body.rb +21 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/map/send.rb +36 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/map/ternary.rb +18 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/map/variable.rb +31 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/map.rb +186 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/range.rb +326 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/rewriter/action.rb +44 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/rewriter.rb +513 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/tree_rewriter/action.rb +243 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/source/tree_rewriter.rb +431 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/static_environment.rb +134 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/syntax_error.rb +21 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/tree_rewriter.rb +133 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/unknown_encoding_in_magic_comment_error.rb +15 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/variables_stack.rb +36 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser/version.rb +5 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/lib/parser.rb +91 -0
- data/vendor/bundle/ruby/3.3.0/gems/parser-3.3.7.2/parser.gemspec +43 -0
- data/vendor/bundle/ruby/3.3.0/gems/pp-0.6.2/BSDL +22 -0
- data/vendor/bundle/ruby/3.3.0/gems/pp-0.6.2/COPYING +56 -0
- data/vendor/bundle/ruby/3.3.0/gems/pp-0.6.2/lib/pp.rb +699 -0
- data/vendor/bundle/ruby/3.3.0/gems/pp-0.6.2/pp.gemspec +35 -0
- data/vendor/bundle/ruby/3.3.0/gems/prettyprint-0.2.0/.github/dependabot.yml +6 -0
- data/vendor/bundle/ruby/3.3.0/gems/prettyprint-0.2.0/.github/workflows/test.yml +41 -0
- data/vendor/bundle/ruby/3.3.0/gems/prettyprint-0.2.0/.gitignore +8 -0
- data/vendor/bundle/ruby/3.3.0/gems/prettyprint-0.2.0/Gemfile +4 -0
- data/vendor/bundle/ruby/3.3.0/gems/prettyprint-0.2.0/LICENSE.txt +22 -0
- data/vendor/bundle/ruby/3.3.0/gems/prettyprint-0.2.0/README.md +43 -0
- data/vendor/bundle/ruby/3.3.0/gems/prettyprint-0.2.0/Rakefile +10 -0
- data/vendor/bundle/ruby/3.3.0/gems/prettyprint-0.2.0/bin/console +14 -0
- data/vendor/bundle/ruby/3.3.0/gems/prettyprint-0.2.0/bin/setup +8 -0
- data/vendor/bundle/ruby/3.3.0/gems/prettyprint-0.2.0/lib/prettyprint.rb +558 -0
- data/vendor/bundle/ruby/3.3.0/gems/prettyprint-0.2.0/prettyprint.gemspec +29 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/CONTRIBUTING.rdoc +219 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/CVE-2013-0256.rdoc +49 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/ExampleMarkdown.md +39 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/ExampleRDoc.rdoc +210 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/History.rdoc +1668 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/LEGAL.rdoc +50 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/LICENSE.rdoc +59 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/README.rdoc +142 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/RI.md +842 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/TODO.rdoc +60 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/exe/rdoc +43 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/exe/ri +12 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_object/alias.rb +111 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_object/anon_class.rb +10 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_object/any_method.rb +379 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_object/attr.rb +175 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_object/class_module.rb +871 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_object/constant.rb +186 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_object/context/section.rb +175 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_object/context.rb +1264 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_object/extend.rb +9 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_object/ghost_method.rb +6 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_object/include.rb +9 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_object/meta_method.rb +6 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_object/method_attr.rb +430 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_object/mixin.rb +120 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_object/normal_class.rb +92 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_object/normal_module.rb +73 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_object/require.rb +51 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_object/single_class.rb +30 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_object/top_level.rb +291 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_object.rb +426 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/code_objects.rb +5 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/comment.rb +239 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/cross_reference.rb +228 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/encoding.rb +120 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/erb_partial.rb +18 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/erbio.rb +37 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/darkfish.rb +824 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/json_index.rb +300 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/markup.rb +159 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/pot/message_extractor.rb +68 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/pot/po.rb +84 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/pot/po_entry.rb +141 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/pot.rb +99 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/ri.rb +30 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/_footer.rhtml +5 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/_head.rhtml +43 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml +19 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml +34 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml +15 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml +9 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml +15 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml +15 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml +21 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/_sidebar_navigation.rhtml +11 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml +32 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml +6 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml +14 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml +11 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml +39 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/_sidebar_toggle.rhtml +3 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/class.rhtml +206 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/css/fonts.css +167 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/css/rdoc.css +668 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/fonts/Lato-Light.ttf +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/fonts/Lato-LightItalic.ttf +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/fonts/Lato-Regular.ttf +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/fonts/Lato-RegularItalic.ttf +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/add.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/arrow_up.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/brick.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/brick_link.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/bug.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/bullet_black.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/bullet_toggle_minus.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/bullet_toggle_plus.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/date.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/delete.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/find.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/loadingAnimation.gif +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/macFFBgHack.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/package.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/page_green.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/page_white_text.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/page_white_width.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/plugin.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/ruby.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/tag_blue.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/tag_green.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/transparent.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/wrench.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/wrench_orange.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/images/zoom.png +0 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/index.rhtml +23 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/js/darkfish.js +120 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/js/search.js +110 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/page.rhtml +18 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/servlet_not_found.rhtml +20 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/servlet_root.rhtml +65 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml +70 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/json_index/js/navigation.js +105 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator/template/json_index/js/searcher.js +229 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/generator.rb +51 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/i18n/locale.rb +102 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/i18n/text.rb +126 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/i18n.rb +10 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/known_classes.rb +74 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markdown/entities.rb +2131 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markdown/literals.kpeg +21 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markdown/literals.rb +454 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markdown.kpeg +1244 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markdown.rb +16793 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/attr_changer.rb +22 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/attr_span.rb +35 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/attribute_manager.rb +405 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/attributes.rb +70 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/blank_line.rb +27 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/block_quote.rb +14 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/document.rb +164 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/formatter.rb +272 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/hard_break.rb +31 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/heading.rb +78 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/include.rb +42 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/indented_paragraph.rb +47 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/list.rb +101 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/list_item.rb +99 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/paragraph.rb +28 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/parser.rb +585 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/pre_process.rb +318 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/raw.rb +69 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/regexp_handling.rb +40 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/rule.rb +20 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/table.rb +56 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/to_ansi.rb +93 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/to_bs.rb +102 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/to_html.rb +452 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/to_html_crossref.rb +226 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/to_html_snippet.rb +287 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/to_joined_paragraph.rb +46 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/to_label.rb +74 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/to_markdown.rb +191 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/to_rdoc.rb +352 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/to_table_of_contents.rb +88 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/to_test.rb +69 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/to_tt_only.rb +120 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup/verbatim.rb +83 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/markup.rb +240 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/options.rb +1397 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/parser/c.rb +1260 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/parser/changelog.rb +350 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/parser/markdown.rb +22 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/parser/prism_ruby.rb +1099 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/parser/rd.rb +22 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/parser/ripper_state_lex.rb +302 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/parser/ruby.rb +2381 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/parser/ruby_tools.rb +165 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/parser/simple.rb +61 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/parser/text.rb +11 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/parser.rb +297 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/rd/block_parser.rb +1706 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/rd/block_parser.ry +643 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/rd/inline.rb +71 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/rd/inline_parser.rb +1854 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/rd/inline_parser.ry +593 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/rd.rb +99 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/rdoc.rb +566 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/ri/driver.rb +1558 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/ri/formatter.rb +6 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/ri/paths.rb +171 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/ri/store.rb +6 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/ri/task.rb +71 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/ri.rb +20 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/rubygems_hook.rb +330 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/servlet.rb +451 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/stats/normal.rb +58 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/stats/quiet.rb +59 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/stats/verbose.rb +44 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/stats.rb +461 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/store.rb +1001 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/task.rb +354 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/text.rb +322 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/token_stream.rb +118 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/tom_doc.rb +257 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc/version.rb +10 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rdoc.rb +211 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/lib/rubygems_plugin.rb +23 -0
- data/vendor/bundle/ruby/3.3.0/gems/rdoc-6.12.0/man/ri.1 +247 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/BSDL +22 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/COPYING +56 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/README.md +94 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/lib/reline/config.rb +373 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/lib/reline/face.rb +199 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/lib/reline/history.rb +76 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/lib/reline/io/ansi.rb +325 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/lib/reline/io/dumb.rb +120 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/lib/reline/io/windows.rb +530 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/lib/reline/io.rb +55 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/lib/reline/key_actor/base.rb +37 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/lib/reline/key_actor/composite.rb +17 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/lib/reline/key_actor/emacs.rb +517 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/lib/reline/key_actor/vi_command.rb +518 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/lib/reline/key_actor/vi_insert.rb +517 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/lib/reline/key_actor.rb +8 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/lib/reline/key_stroke.rb +119 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/lib/reline/kill_ring.rb +125 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/lib/reline/line_editor.rb +2382 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/lib/reline/unicode/east_asian_width.rb +1267 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/lib/reline/unicode.rb +415 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/lib/reline/version.rb +3 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/lib/reline.rb +519 -0
- data/vendor/bundle/ruby/3.3.0/gems/reline-0.6.0/license_of_rb-readline +25 -0
- data/vendor/bundle/ruby/3.3.0/plugins/rdoc_plugin.rb +1 -0
- data/vendor/bundle/ruby/3.3.0/specifications/ast-2.4.3.gemspec +29 -0
- data/vendor/bundle/ruby/3.3.0/specifications/debug-1.10.0.gemspec +32 -0
- data/vendor/bundle/ruby/3.3.0/specifications/io-console-0.8.0.gemspec +25 -0
- data/vendor/bundle/ruby/3.3.0/specifications/irb-1.15.1.gemspec +31 -0
- data/vendor/bundle/ruby/3.3.0/specifications/parser-3.3.7.2.gemspec +37 -0
- data/vendor/bundle/ruby/3.3.0/specifications/pp-0.6.2.gemspec +27 -0
- data/vendor/bundle/ruby/3.3.0/specifications/prettyprint-0.2.0.gemspec +23 -0
- data/vendor/bundle/ruby/3.3.0/specifications/rdoc-6.12.0.gemspec +31 -0
- data/vendor/bundle/ruby/3.3.0/specifications/reline-0.6.0.gemspec +26 -0
- metadata +499 -3
@@ -0,0 +1,2659 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
return if ENV['RUBY_DEBUG_ENABLE'] == '0'
|
4
|
+
|
5
|
+
# skip to load debugger for bundle exec
|
6
|
+
|
7
|
+
if $0.end_with?('bin/bundle') && ARGV.first == 'exec'
|
8
|
+
trace_var(:$0) do |file|
|
9
|
+
trace_var(:$0, nil)
|
10
|
+
if /-r (#{Regexp.escape(__dir__)}\S+)/ =~ ENV['RUBYOPT']
|
11
|
+
lib = $1
|
12
|
+
$LOADED_FEATURES.delete_if{|path| path.start_with?(__dir__)}
|
13
|
+
ENV['RUBY_DEBUG_INITIAL_SUSPEND_PATH'] = file
|
14
|
+
require lib
|
15
|
+
ENV['RUBY_DEBUG_INITIAL_SUSPEND_PATH'] = nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
return
|
20
|
+
end
|
21
|
+
|
22
|
+
# restore RUBYOPT
|
23
|
+
if (added_opt = ENV['RUBY_DEBUG_ADDED_RUBYOPT']) &&
|
24
|
+
(rubyopt = ENV['RUBYOPT']) &&
|
25
|
+
rubyopt.end_with?(added_opt)
|
26
|
+
|
27
|
+
ENV['RUBYOPT'] = rubyopt.delete_suffix(added_opt)
|
28
|
+
ENV['RUBY_DEBUG_ADDED_RUBYOPT'] = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
require_relative 'frame_info'
|
32
|
+
require_relative 'config'
|
33
|
+
require_relative 'thread_client'
|
34
|
+
require_relative 'source_repository'
|
35
|
+
require_relative 'breakpoint'
|
36
|
+
require_relative 'tracer'
|
37
|
+
|
38
|
+
# To prevent loading old lib/debug.rb in Ruby 2.6 to 3.0
|
39
|
+
$LOADED_FEATURES << 'debug.rb'
|
40
|
+
$LOADED_FEATURES << File.expand_path(File.join(__dir__, '..', 'debug.rb'))
|
41
|
+
require 'debug' # invalidate the $LOADED_FEATURE cache
|
42
|
+
|
43
|
+
require 'json' if ENV['RUBY_DEBUG_TEST_UI'] == 'terminal'
|
44
|
+
require 'pp'
|
45
|
+
|
46
|
+
class RubyVM::InstructionSequence
|
47
|
+
def traceable_lines_norec lines
|
48
|
+
code = self.to_a[13]
|
49
|
+
line = 0
|
50
|
+
code.each{|e|
|
51
|
+
case e
|
52
|
+
when Integer
|
53
|
+
line = e
|
54
|
+
when Symbol
|
55
|
+
if /\ARUBY_EVENT_/ =~ e.to_s
|
56
|
+
lines[line] = [e, *lines[line]]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
def traceable_lines_rec lines
|
63
|
+
self.each_child{|ci| ci.traceable_lines_rec(lines)}
|
64
|
+
traceable_lines_norec lines
|
65
|
+
end
|
66
|
+
|
67
|
+
def type
|
68
|
+
self.to_a[9]
|
69
|
+
end unless method_defined?(:type)
|
70
|
+
|
71
|
+
def parameters_symbols
|
72
|
+
ary = self.to_a
|
73
|
+
argc = ary[4][:arg_size]
|
74
|
+
locals = ary.to_a[10]
|
75
|
+
locals[0...argc]
|
76
|
+
end unless method_defined?(:parameters_symbols)
|
77
|
+
|
78
|
+
def last_line
|
79
|
+
self.to_a[4][:code_location][2]
|
80
|
+
end unless method_defined?(:last_line)
|
81
|
+
|
82
|
+
def first_line
|
83
|
+
self.to_a[4][:code_location][0]
|
84
|
+
end unless method_defined?(:first_line)
|
85
|
+
end if defined?(RubyVM::InstructionSequence)
|
86
|
+
|
87
|
+
module DEBUGGER__
|
88
|
+
PresetCommands = Struct.new(:commands, :source, :auto_continue)
|
89
|
+
SessionCommand = Struct.new(:block, :repeat, :unsafe, :cancel_auto_continue, :postmortem)
|
90
|
+
|
91
|
+
class PostmortemError < RuntimeError; end
|
92
|
+
|
93
|
+
class Session
|
94
|
+
attr_reader :intercepted_sigint_cmd, :process_group, :subsession_id
|
95
|
+
|
96
|
+
include Color
|
97
|
+
|
98
|
+
def initialize
|
99
|
+
@ui = nil
|
100
|
+
@sr = SourceRepository.new
|
101
|
+
@bps = {} # bp.key => bp
|
102
|
+
# [file, line] => LineBreakpoint
|
103
|
+
# "Error" => CatchBreakpoint
|
104
|
+
# "Foo#bar" => MethodBreakpoint
|
105
|
+
# [:watch, ivar] => WatchIVarBreakpoint
|
106
|
+
# [:check, expr] => CheckBreakpoint
|
107
|
+
#
|
108
|
+
@tracers = {}
|
109
|
+
@th_clients = {} # {Thread => ThreadClient}
|
110
|
+
@q_evt = Queue.new
|
111
|
+
@displays = []
|
112
|
+
@tc = nil
|
113
|
+
@tc_id = 0
|
114
|
+
@preset_command = nil
|
115
|
+
@postmortem_hook = nil
|
116
|
+
@postmortem = false
|
117
|
+
@intercept_trap_sigint = false
|
118
|
+
@intercepted_sigint_cmd = 'DEFAULT'
|
119
|
+
@process_group = ProcessGroup.new
|
120
|
+
@subsession_stack = []
|
121
|
+
@subsession_id = 0
|
122
|
+
|
123
|
+
@frame_map = {} # for DAP: {id => [threadId, frame_depth]} and CDP: {id => frame_depth}
|
124
|
+
@var_map = {1 => [:globals], } # {id => ...} for DAP
|
125
|
+
@src_map = {} # {id => src}
|
126
|
+
|
127
|
+
@scr_id_map = {} # for CDP
|
128
|
+
@obj_map = {} # { object_id => ... } for CDP
|
129
|
+
|
130
|
+
@tp_thread_begin = nil
|
131
|
+
@tp_thread_end = nil
|
132
|
+
|
133
|
+
@commands = {}
|
134
|
+
@unsafe_context = false
|
135
|
+
|
136
|
+
@has_keep_script_lines = defined?(RubyVM.keep_script_lines)
|
137
|
+
|
138
|
+
@tp_load_script = TracePoint.new(:script_compiled){|tp|
|
139
|
+
eval_script = tp.eval_script unless @has_keep_script_lines
|
140
|
+
ThreadClient.current.on_load tp.instruction_sequence, eval_script
|
141
|
+
}
|
142
|
+
@tp_load_script.enable
|
143
|
+
|
144
|
+
@thread_stopper = thread_stopper
|
145
|
+
self.postmortem = CONFIG[:postmortem]
|
146
|
+
|
147
|
+
register_default_command
|
148
|
+
end
|
149
|
+
|
150
|
+
def active?
|
151
|
+
!@q_evt.closed?
|
152
|
+
end
|
153
|
+
|
154
|
+
def remote?
|
155
|
+
@ui.remote?
|
156
|
+
end
|
157
|
+
|
158
|
+
def stop_stepping? file, line, subsession_id = nil
|
159
|
+
if @bps.has_key? [file, line]
|
160
|
+
true
|
161
|
+
elsif subsession_id && @subsession_id != subsession_id
|
162
|
+
true
|
163
|
+
else
|
164
|
+
false
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def activate ui = nil, on_fork: false
|
169
|
+
@ui = ui if ui
|
170
|
+
|
171
|
+
@tp_thread_begin&.disable
|
172
|
+
@tp_thread_end&.disable
|
173
|
+
@tp_thread_begin = nil
|
174
|
+
@tp_thread_end = nil
|
175
|
+
@ui.activate self, on_fork: on_fork
|
176
|
+
|
177
|
+
q = Queue.new
|
178
|
+
first_q = Queue.new
|
179
|
+
@session_server = Thread.new do
|
180
|
+
# make sure `@session_server` is assigned
|
181
|
+
first_q.pop; first_q = nil
|
182
|
+
|
183
|
+
Thread.current.name = 'DEBUGGER__::SESSION@server'
|
184
|
+
Thread.current.abort_on_exception = true
|
185
|
+
|
186
|
+
# Thread management
|
187
|
+
setup_threads
|
188
|
+
thc = get_thread_client Thread.current
|
189
|
+
thc.mark_as_management
|
190
|
+
|
191
|
+
if @ui.respond_to?(:reader_thread) && thc = get_thread_client(@ui.reader_thread)
|
192
|
+
thc.mark_as_management
|
193
|
+
end
|
194
|
+
|
195
|
+
@tp_thread_begin = TracePoint.new(:thread_begin) do |tp|
|
196
|
+
get_thread_client
|
197
|
+
end
|
198
|
+
@tp_thread_begin.enable
|
199
|
+
|
200
|
+
@tp_thread_end = TracePoint.new(:thread_end) do |tp|
|
201
|
+
@th_clients.delete(Thread.current)
|
202
|
+
end
|
203
|
+
@tp_thread_end.enable
|
204
|
+
|
205
|
+
# session start
|
206
|
+
q << true
|
207
|
+
session_server_main
|
208
|
+
end
|
209
|
+
first_q << :ok
|
210
|
+
|
211
|
+
q.pop
|
212
|
+
|
213
|
+
# For activating irb:rdbg with startup config like `RUBY_DEBUG_IRB_CONSOLE=1`
|
214
|
+
# Because in that case the `Config#if_updated` callback would not be triggered
|
215
|
+
if CONFIG[:irb_console] && !CONFIG[:open]
|
216
|
+
activate_irb_integration
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def deactivate
|
221
|
+
get_thread_client.deactivate
|
222
|
+
@thread_stopper.disable
|
223
|
+
@tp_load_script.disable
|
224
|
+
@tp_thread_begin.disable
|
225
|
+
@tp_thread_end.disable
|
226
|
+
@bps.each_value{|bp| bp.disable}
|
227
|
+
@th_clients.each_value{|thc| thc.close}
|
228
|
+
@tracers.values.each{|t| t.disable}
|
229
|
+
@q_evt.close
|
230
|
+
@ui&.deactivate
|
231
|
+
@ui = nil
|
232
|
+
end
|
233
|
+
|
234
|
+
def reset_ui ui
|
235
|
+
@ui.deactivate
|
236
|
+
@ui = ui
|
237
|
+
|
238
|
+
# activate new ui
|
239
|
+
@tp_thread_begin.disable
|
240
|
+
@tp_thread_end.disable
|
241
|
+
@ui.activate self
|
242
|
+
if @ui.respond_to?(:reader_thread) && thc = get_thread_client(@ui.reader_thread)
|
243
|
+
thc.mark_as_management
|
244
|
+
end
|
245
|
+
@tp_thread_begin.enable
|
246
|
+
@tp_thread_end.enable
|
247
|
+
end
|
248
|
+
|
249
|
+
def pop_event
|
250
|
+
@q_evt.pop
|
251
|
+
end
|
252
|
+
|
253
|
+
def session_server_main
|
254
|
+
while evt = pop_event
|
255
|
+
process_event evt
|
256
|
+
end
|
257
|
+
ensure
|
258
|
+
deactivate
|
259
|
+
end
|
260
|
+
|
261
|
+
def request_tc(req)
|
262
|
+
@tc << req
|
263
|
+
end
|
264
|
+
|
265
|
+
def request_tc_with_restarted_threads(req)
|
266
|
+
restart_all_threads
|
267
|
+
request_tc(req)
|
268
|
+
end
|
269
|
+
|
270
|
+
def request_eval type, src
|
271
|
+
request_tc_with_restarted_threads [:eval, type, src]
|
272
|
+
end
|
273
|
+
|
274
|
+
def process_event evt
|
275
|
+
# variable `@internal_info` is only used for test
|
276
|
+
tc, output, ev, @internal_info, *ev_args = evt
|
277
|
+
|
278
|
+
output.each{|str| @ui.puts str} if ev != :suspend
|
279
|
+
|
280
|
+
# special event, tc is nil
|
281
|
+
# and we don't want to set @tc to the newly created thread's ThreadClient
|
282
|
+
if ev == :thread_begin
|
283
|
+
th = ev_args.shift
|
284
|
+
q = ev_args.shift
|
285
|
+
on_thread_begin th
|
286
|
+
q << true
|
287
|
+
|
288
|
+
return
|
289
|
+
end
|
290
|
+
|
291
|
+
@tc = tc
|
292
|
+
|
293
|
+
case ev
|
294
|
+
when :init
|
295
|
+
enter_subsession
|
296
|
+
wait_command_loop
|
297
|
+
when :load
|
298
|
+
iseq, src = ev_args
|
299
|
+
on_load iseq, src
|
300
|
+
request_tc :continue
|
301
|
+
|
302
|
+
when :trace
|
303
|
+
trace_id, msg = ev_args
|
304
|
+
if t = @tracers.values.find{|t| t.object_id == trace_id}
|
305
|
+
t.puts msg
|
306
|
+
end
|
307
|
+
request_tc :continue
|
308
|
+
|
309
|
+
when :suspend
|
310
|
+
enter_subsession if ev_args.first != :replay
|
311
|
+
output.each{|str| @ui.puts str} unless @ui.ignore_output_on_suspend?
|
312
|
+
|
313
|
+
case ev_args.first
|
314
|
+
when :breakpoint
|
315
|
+
bp, i = bp_index ev_args[1]
|
316
|
+
clean_bps unless bp
|
317
|
+
@ui.event :suspend_bp, i, bp, @tc.id
|
318
|
+
when :trap
|
319
|
+
@ui.event :suspend_trap, sig = ev_args[1], @tc.id
|
320
|
+
|
321
|
+
if sig == :SIGINT && (@intercepted_sigint_cmd.kind_of?(Proc) || @intercepted_sigint_cmd.kind_of?(String))
|
322
|
+
@ui.puts "#{@intercepted_sigint_cmd.inspect} is registered as SIGINT handler."
|
323
|
+
@ui.puts "`sigint` command execute it."
|
324
|
+
end
|
325
|
+
else
|
326
|
+
@ui.event :suspended, @tc.id
|
327
|
+
end
|
328
|
+
|
329
|
+
if @displays.empty?
|
330
|
+
wait_command_loop
|
331
|
+
else
|
332
|
+
request_eval :display, @displays
|
333
|
+
end
|
334
|
+
when :result
|
335
|
+
raise "[BUG] not in subsession" if @subsession_stack.empty?
|
336
|
+
|
337
|
+
case ev_args.first
|
338
|
+
when :try_display
|
339
|
+
failed_results = ev_args[1]
|
340
|
+
if failed_results.size > 0
|
341
|
+
i, _msg = failed_results.last
|
342
|
+
if i+1 == @displays.size
|
343
|
+
@ui.puts "canceled: #{@displays.pop}"
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
stop_all_threads
|
348
|
+
when :method_breakpoint, :watch_breakpoint
|
349
|
+
bp = ev_args[1]
|
350
|
+
if bp
|
351
|
+
add_bp(bp)
|
352
|
+
show_bps bp
|
353
|
+
else
|
354
|
+
# can't make a bp
|
355
|
+
end
|
356
|
+
when :trace_pass
|
357
|
+
obj_id = ev_args[1]
|
358
|
+
obj_inspect = ev_args[2]
|
359
|
+
opt = ev_args[3]
|
360
|
+
add_tracer ObjectTracer.new(@ui, obj_id, obj_inspect, **opt)
|
361
|
+
stop_all_threads
|
362
|
+
else
|
363
|
+
stop_all_threads
|
364
|
+
end
|
365
|
+
|
366
|
+
wait_command_loop
|
367
|
+
|
368
|
+
when :protocol_result
|
369
|
+
process_protocol_result ev_args
|
370
|
+
wait_command_loop
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
def add_preset_commands name, cmds, kick: true, continue: true
|
375
|
+
cs = cmds.map{|c|
|
376
|
+
c.each_line.map{|line|
|
377
|
+
line = line.strip.gsub(/\A\s*\#.*/, '').strip
|
378
|
+
line unless line.empty?
|
379
|
+
}.compact
|
380
|
+
}.flatten.compact
|
381
|
+
|
382
|
+
if @preset_command && !@preset_command.commands.empty?
|
383
|
+
@preset_command.commands += cs
|
384
|
+
else
|
385
|
+
@preset_command = PresetCommands.new(cs, name, continue)
|
386
|
+
end
|
387
|
+
|
388
|
+
ThreadClient.current.on_init name if kick
|
389
|
+
end
|
390
|
+
|
391
|
+
def source iseq
|
392
|
+
if !CONFIG[:no_color]
|
393
|
+
@sr.get_colored(iseq)
|
394
|
+
else
|
395
|
+
@sr.get(iseq)
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
def inspect
|
400
|
+
"DEBUGGER__::SESSION"
|
401
|
+
end
|
402
|
+
|
403
|
+
def wait_command_loop
|
404
|
+
loop do
|
405
|
+
case wait_command
|
406
|
+
when :retry
|
407
|
+
# nothing
|
408
|
+
else
|
409
|
+
break
|
410
|
+
end
|
411
|
+
rescue Interrupt
|
412
|
+
@ui.puts "\n^C"
|
413
|
+
retry
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
def prompt
|
418
|
+
if @postmortem
|
419
|
+
'(rdbg:postmortem) '
|
420
|
+
elsif @process_group.multi?
|
421
|
+
"(rdbg@#{process_info}) "
|
422
|
+
else
|
423
|
+
'(rdbg) '
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
def wait_command
|
428
|
+
if @preset_command
|
429
|
+
if @preset_command.commands.empty?
|
430
|
+
if @preset_command.auto_continue
|
431
|
+
@preset_command = nil
|
432
|
+
|
433
|
+
leave_subsession :continue
|
434
|
+
return
|
435
|
+
else
|
436
|
+
@preset_command = nil
|
437
|
+
return :retry
|
438
|
+
end
|
439
|
+
else
|
440
|
+
line = @preset_command.commands.shift
|
441
|
+
@ui.puts "(rdbg:#{@preset_command.source}) #{line}"
|
442
|
+
end
|
443
|
+
else
|
444
|
+
@ui.puts "INTERNAL_INFO: #{JSON.generate(@internal_info)}" if ENV['RUBY_DEBUG_TEST_UI'] == 'terminal'
|
445
|
+
line = @ui.readline prompt
|
446
|
+
end
|
447
|
+
|
448
|
+
case line
|
449
|
+
when String
|
450
|
+
process_command line
|
451
|
+
when Hash
|
452
|
+
process_protocol_request line # defined in server.rb
|
453
|
+
else
|
454
|
+
raise "unexpected input: #{line.inspect}"
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
private def register_command *names,
|
459
|
+
repeat: false, unsafe: true, cancel_auto_continue: false, postmortem: true,
|
460
|
+
&b
|
461
|
+
cmd = SessionCommand.new(b, repeat, unsafe, cancel_auto_continue, postmortem)
|
462
|
+
|
463
|
+
names.each{|name|
|
464
|
+
@commands[name] = cmd
|
465
|
+
}
|
466
|
+
end
|
467
|
+
|
468
|
+
def register_default_command
|
469
|
+
### Control flow
|
470
|
+
|
471
|
+
# * `s[tep]`
|
472
|
+
# * Step in. Resume the program until next breakable point.
|
473
|
+
# * `s[tep] <n>`
|
474
|
+
# * Step in, resume the program at `<n>`th breakable point.
|
475
|
+
register_command 's', 'step',
|
476
|
+
repeat: true,
|
477
|
+
cancel_auto_continue: true,
|
478
|
+
postmortem: false do |arg|
|
479
|
+
step_command :in, arg
|
480
|
+
end
|
481
|
+
|
482
|
+
# * `n[ext]`
|
483
|
+
# * Step over. Resume the program until next line.
|
484
|
+
# * `n[ext] <n>`
|
485
|
+
# * Step over, same as `step <n>`.
|
486
|
+
register_command 'n', 'next',
|
487
|
+
repeat: true,
|
488
|
+
cancel_auto_continue: true,
|
489
|
+
postmortem: false do |arg|
|
490
|
+
step_command :next, arg
|
491
|
+
end
|
492
|
+
|
493
|
+
# * `fin[ish]`
|
494
|
+
# * Finish this frame. Resume the program until the current frame is finished.
|
495
|
+
# * `fin[ish] <n>`
|
496
|
+
# * Finish `<n>`th frames.
|
497
|
+
register_command 'fin', 'finish',
|
498
|
+
repeat: true,
|
499
|
+
cancel_auto_continue: true,
|
500
|
+
postmortem: false do |arg|
|
501
|
+
if arg&.to_i == 0
|
502
|
+
raise 'finish command with 0 does not make sense.'
|
503
|
+
end
|
504
|
+
|
505
|
+
step_command :finish, arg
|
506
|
+
end
|
507
|
+
|
508
|
+
# * `u[ntil]`
|
509
|
+
# * Similar to `next` command, but only stop later lines or the end of the current frame.
|
510
|
+
# * Similar to gdb's `advance` command.
|
511
|
+
# * `u[ntil] <[file:]line>`
|
512
|
+
# * Run til the program reaches given location or the end of the current frame.
|
513
|
+
# * `u[ntil] <name>`
|
514
|
+
# * Run til the program invokes a method `<name>`. `<name>` can be a regexp with `/name/`.
|
515
|
+
register_command 'u', 'until',
|
516
|
+
repeat: true,
|
517
|
+
cancel_auto_continue: true,
|
518
|
+
postmortem: false do |arg|
|
519
|
+
|
520
|
+
step_command :until, arg
|
521
|
+
end
|
522
|
+
|
523
|
+
# * `c` or `cont` or `continue`
|
524
|
+
# * Resume the program.
|
525
|
+
register_command 'c', 'cont', 'continue',
|
526
|
+
repeat: true,
|
527
|
+
cancel_auto_continue: true do |arg|
|
528
|
+
leave_subsession :continue
|
529
|
+
end
|
530
|
+
|
531
|
+
# * `q[uit]` or `Ctrl-D`
|
532
|
+
# * Finish debugger (with the debuggee process on non-remote debugging).
|
533
|
+
register_command 'q', 'quit' do |arg|
|
534
|
+
if ask 'Really quit?'
|
535
|
+
@ui.quit arg.to_i do
|
536
|
+
request_tc :quit
|
537
|
+
end
|
538
|
+
leave_subsession :continue
|
539
|
+
else
|
540
|
+
next :retry
|
541
|
+
end
|
542
|
+
end
|
543
|
+
|
544
|
+
# * `q[uit]!`
|
545
|
+
# * Same as q[uit] but without the confirmation prompt.
|
546
|
+
register_command 'q!', 'quit!', unsafe: false do |arg|
|
547
|
+
@ui.quit arg.to_i do
|
548
|
+
request_tc :quit
|
549
|
+
end
|
550
|
+
leave_subsession :continue
|
551
|
+
end
|
552
|
+
|
553
|
+
# * `kill`
|
554
|
+
# * Stop the debuggee process with `Kernel#exit!`.
|
555
|
+
register_command 'kill' do |arg|
|
556
|
+
if ask 'Really kill?'
|
557
|
+
exit! (arg || 1).to_i
|
558
|
+
else
|
559
|
+
next :retry
|
560
|
+
end
|
561
|
+
end
|
562
|
+
|
563
|
+
# * `kill!`
|
564
|
+
# * Same as kill but without the confirmation prompt.
|
565
|
+
register_command 'kill!', unsafe: false do |arg|
|
566
|
+
exit! (arg || 1).to_i
|
567
|
+
end
|
568
|
+
|
569
|
+
# * `sigint`
|
570
|
+
# * Execute SIGINT handler registered by the debuggee.
|
571
|
+
# * Note that this command should be used just after stop by `SIGINT`.
|
572
|
+
register_command 'sigint' do
|
573
|
+
begin
|
574
|
+
case cmd = @intercepted_sigint_cmd
|
575
|
+
when nil, 'IGNORE', :IGNORE, 'DEFAULT', :DEFAULT
|
576
|
+
# ignore
|
577
|
+
when String
|
578
|
+
eval(cmd)
|
579
|
+
when Proc
|
580
|
+
cmd.call
|
581
|
+
end
|
582
|
+
|
583
|
+
leave_subsession :continue
|
584
|
+
|
585
|
+
rescue Exception => e
|
586
|
+
@ui.puts "Exception: #{e}"
|
587
|
+
@ui.puts e.backtrace.map{|line| " #{e}"}
|
588
|
+
next :retry
|
589
|
+
end
|
590
|
+
end
|
591
|
+
|
592
|
+
### Breakpoint
|
593
|
+
|
594
|
+
# * `b[reak]`
|
595
|
+
# * Show all breakpoints.
|
596
|
+
# * `b[reak] <line>`
|
597
|
+
# * Set breakpoint on `<line>` at the current frame's file.
|
598
|
+
# * `b[reak] <file>:<line>` or `<file> <line>`
|
599
|
+
# * Set breakpoint on `<file>:<line>`.
|
600
|
+
# * `b[reak] <class>#<name>`
|
601
|
+
# * Set breakpoint on the method `<class>#<name>`.
|
602
|
+
# * `b[reak] <expr>.<name>`
|
603
|
+
# * Set breakpoint on the method `<expr>.<name>`.
|
604
|
+
# * `b[reak] ... if: <expr>`
|
605
|
+
# * break if `<expr>` is true at specified location.
|
606
|
+
# * `b[reak] ... pre: <command>`
|
607
|
+
# * break and run `<command>` before stopping.
|
608
|
+
# * `b[reak] ... do: <command>`
|
609
|
+
# * break and run `<command>`, and continue.
|
610
|
+
# * `b[reak] ... path: <path>`
|
611
|
+
# * break if the path matches to `<path>`. `<path>` can be a regexp with `/regexp/`.
|
612
|
+
# * `b[reak] if: <expr>`
|
613
|
+
# * break if: `<expr>` is true at any lines.
|
614
|
+
# * Note that this feature is super slow.
|
615
|
+
register_command 'b', 'break', postmortem: false, unsafe: false do |arg|
|
616
|
+
if arg == nil
|
617
|
+
show_bps
|
618
|
+
next :retry
|
619
|
+
else
|
620
|
+
case bp = repl_add_breakpoint(arg)
|
621
|
+
when :noretry
|
622
|
+
when nil
|
623
|
+
next :retry
|
624
|
+
else
|
625
|
+
show_bps bp
|
626
|
+
next :retry
|
627
|
+
end
|
628
|
+
end
|
629
|
+
end
|
630
|
+
|
631
|
+
# * `catch <Error>`
|
632
|
+
# * Set breakpoint on raising `<Error>`.
|
633
|
+
# * `catch ... if: <expr>`
|
634
|
+
# * stops only if `<expr>` is true as well.
|
635
|
+
# * `catch ... pre: <command>`
|
636
|
+
# * runs `<command>` before stopping.
|
637
|
+
# * `catch ... do: <command>`
|
638
|
+
# * stops and run `<command>`, and continue.
|
639
|
+
# * `catch ... path: <path>`
|
640
|
+
# * stops if the exception is raised from a `<path>`. `<path>` can be a regexp with `/regexp/`.
|
641
|
+
register_command 'catch', postmortem: false, unsafe: false do |arg|
|
642
|
+
if arg
|
643
|
+
bp = repl_add_catch_breakpoint arg
|
644
|
+
show_bps bp if bp
|
645
|
+
else
|
646
|
+
show_bps
|
647
|
+
end
|
648
|
+
|
649
|
+
:retry
|
650
|
+
end
|
651
|
+
|
652
|
+
# * `watch @ivar`
|
653
|
+
# * Stop the execution when the result of current scope's `@ivar` is changed.
|
654
|
+
# * Note that this feature is super slow.
|
655
|
+
# * `watch ... if: <expr>`
|
656
|
+
# * stops only if `<expr>` is true as well.
|
657
|
+
# * `watch ... pre: <command>`
|
658
|
+
# * runs `<command>` before stopping.
|
659
|
+
# * `watch ... do: <command>`
|
660
|
+
# * stops and run `<command>`, and continue.
|
661
|
+
# * `watch ... path: <path>`
|
662
|
+
# * stops if the path matches `<path>`. `<path>` can be a regexp with `/regexp/`.
|
663
|
+
register_command 'wat', 'watch', postmortem: false, unsafe: false do |arg|
|
664
|
+
if arg && arg.match?(/\A@\w+/)
|
665
|
+
repl_add_watch_breakpoint(arg)
|
666
|
+
else
|
667
|
+
show_bps
|
668
|
+
:retry
|
669
|
+
end
|
670
|
+
end
|
671
|
+
|
672
|
+
# * `del[ete]`
|
673
|
+
# * delete all breakpoints.
|
674
|
+
# * `del[ete] <bpnum>`
|
675
|
+
# * delete specified breakpoint.
|
676
|
+
register_command 'del', 'delete', postmortem: false, unsafe: false do |arg|
|
677
|
+
case arg
|
678
|
+
when nil
|
679
|
+
show_bps
|
680
|
+
if ask "Remove all breakpoints?", 'N'
|
681
|
+
delete_bp
|
682
|
+
end
|
683
|
+
when /\d+/
|
684
|
+
bp = delete_bp arg.to_i
|
685
|
+
else
|
686
|
+
nil
|
687
|
+
end
|
688
|
+
@ui.puts "deleted: \##{bp[0]} #{bp[1]}" if bp
|
689
|
+
:retry
|
690
|
+
end
|
691
|
+
|
692
|
+
### Information
|
693
|
+
|
694
|
+
# * `bt` or `backtrace`
|
695
|
+
# * Show backtrace (frame) information.
|
696
|
+
# * `bt <num>` or `backtrace <num>`
|
697
|
+
# * Only shows first `<num>` frames.
|
698
|
+
# * `bt /regexp/` or `backtrace /regexp/`
|
699
|
+
# * Only shows frames with method name or location info that matches `/regexp/`.
|
700
|
+
# * `bt <num> /regexp/` or `backtrace <num> /regexp/`
|
701
|
+
# * Only shows first `<num>` frames with method name or location info that matches `/regexp/`.
|
702
|
+
register_command 'bt', 'backtrace', unsafe: false do |arg|
|
703
|
+
case arg
|
704
|
+
when /\A(\d+)\z/
|
705
|
+
request_tc_with_restarted_threads [:show, :backtrace, arg.to_i, nil]
|
706
|
+
when /\A\/(.*)\/\z/
|
707
|
+
pattern = $1
|
708
|
+
request_tc_with_restarted_threads [:show, :backtrace, nil, Regexp.compile(pattern)]
|
709
|
+
when /\A(\d+)\s+\/(.*)\/\z/
|
710
|
+
max, pattern = $1, $2
|
711
|
+
request_tc_with_restarted_threads [:show, :backtrace, max.to_i, Regexp.compile(pattern)]
|
712
|
+
else
|
713
|
+
request_tc_with_restarted_threads [:show, :backtrace, nil, nil]
|
714
|
+
end
|
715
|
+
end
|
716
|
+
|
717
|
+
# * `l[ist]`
|
718
|
+
# * Show current frame's source code.
|
719
|
+
# * Next `list` command shows the successor lines.
|
720
|
+
# * `l[ist] -`
|
721
|
+
# * Show predecessor lines as opposed to the `list` command.
|
722
|
+
# * `l[ist] <start>` or `l[ist] <start>-<end>`
|
723
|
+
# * Show current frame's source code from the line <start> to <end> if given.
|
724
|
+
register_command 'l', 'list', repeat: true, unsafe: false do |arg|
|
725
|
+
case arg ? arg.strip : nil
|
726
|
+
when /\A(\d+)\z/
|
727
|
+
request_tc [:show, :list, {start_line: arg.to_i - 1}]
|
728
|
+
when /\A-\z/
|
729
|
+
request_tc [:show, :list, {dir: -1}]
|
730
|
+
when /\A(\d+)-(\d+)\z/
|
731
|
+
request_tc [:show, :list, {start_line: $1.to_i - 1, end_line: $2.to_i}]
|
732
|
+
when nil
|
733
|
+
request_tc [:show, :list]
|
734
|
+
else
|
735
|
+
@ui.puts "Can not handle list argument: #{arg}"
|
736
|
+
:retry
|
737
|
+
end
|
738
|
+
end
|
739
|
+
|
740
|
+
# * `whereami`
|
741
|
+
# * Show the current frame with source code.
|
742
|
+
register_command 'whereami', unsafe: false do
|
743
|
+
request_tc [:show, :whereami]
|
744
|
+
end
|
745
|
+
|
746
|
+
# * `edit`
|
747
|
+
# * Open the current file on the editor (use `EDITOR` environment variable).
|
748
|
+
# * Note that edited file will not be reloaded.
|
749
|
+
# * `edit <file>`
|
750
|
+
# * Open <file> on the editor.
|
751
|
+
register_command 'edit' do |arg|
|
752
|
+
if @ui.remote?
|
753
|
+
@ui.puts "not supported on the remote console."
|
754
|
+
next :retry
|
755
|
+
end
|
756
|
+
|
757
|
+
begin
|
758
|
+
arg = resolve_path(arg) if arg
|
759
|
+
rescue Errno::ENOENT
|
760
|
+
@ui.puts "not found: #{arg}"
|
761
|
+
next :retry
|
762
|
+
end
|
763
|
+
|
764
|
+
request_tc [:show, :edit, arg]
|
765
|
+
end
|
766
|
+
|
767
|
+
info_subcommands = nil
|
768
|
+
info_subcommands_abbrev = nil
|
769
|
+
|
770
|
+
# * `i[nfo]`
|
771
|
+
# * Show information about current frame (local/instance variables and defined constants).
|
772
|
+
# * `i[nfo]` <subcommand>
|
773
|
+
# * `info` has the following sub-commands.
|
774
|
+
# * Sub-commands can be specified with few letters which is unambiguous, like `l` for 'locals'.
|
775
|
+
# * `i[nfo] l or locals or local_variables`
|
776
|
+
# * Show information about the current frame (local variables)
|
777
|
+
# * It includes `self` as `%self` and a return value as `_return`.
|
778
|
+
# * `i[nfo] i or ivars or instance_variables`
|
779
|
+
# * Show information about instance variables about `self`.
|
780
|
+
# * `info ivars <expr>` shows the instance variables of the result of `<expr>`.
|
781
|
+
# * `i[nfo] c or consts or constants`
|
782
|
+
# * Show information about accessible constants except toplevel constants.
|
783
|
+
# * `info consts <expr>` shows the constants of a class/module of the result of `<expr>`
|
784
|
+
# * `i[nfo] g or globals or global_variables`
|
785
|
+
# * Show information about global variables
|
786
|
+
# * `i[nfo] th or threads`
|
787
|
+
# * Show all threads (same as `th[read]`).
|
788
|
+
# * `i[nfo] b or breakpoints or w or watchpoints`
|
789
|
+
# * Show all breakpoints and watchpoints.
|
790
|
+
# * `i[nfo] ... /regexp/`
|
791
|
+
# * Filter the output with `/regexp/`.
|
792
|
+
register_command 'i', 'info', unsafe: false do |arg|
|
793
|
+
if /\/(.+)\/\z/ =~ arg
|
794
|
+
pat = Regexp.compile($1)
|
795
|
+
sub = $~.pre_match.strip
|
796
|
+
else
|
797
|
+
sub = arg
|
798
|
+
end
|
799
|
+
|
800
|
+
if /\A(.+?)\b(.+)/ =~ sub
|
801
|
+
sub = $1
|
802
|
+
opt = $2.strip
|
803
|
+
opt = nil if opt.empty?
|
804
|
+
end
|
805
|
+
|
806
|
+
if sub && !info_subcommands
|
807
|
+
info_subcommands = {
|
808
|
+
locals: %w[ locals local_variables ],
|
809
|
+
ivars: %w[ ivars instance_variables ],
|
810
|
+
consts: %w[ consts constants ],
|
811
|
+
globals:%w[ globals global_variables ],
|
812
|
+
threads:%w[ threads ],
|
813
|
+
breaks: %w[ breakpoints ],
|
814
|
+
watchs: %w[ watchpoints ],
|
815
|
+
}
|
816
|
+
|
817
|
+
require_relative 'abbrev_command'
|
818
|
+
info_subcommands_abbrev = AbbrevCommand.new(info_subcommands)
|
819
|
+
end
|
820
|
+
|
821
|
+
if sub
|
822
|
+
sub = info_subcommands_abbrev.search sub, :unknown do |candidates|
|
823
|
+
# note: unreached now
|
824
|
+
@ui.puts "Ambiguous command '#{sub}': #{candidates.join(' ')}"
|
825
|
+
end
|
826
|
+
end
|
827
|
+
|
828
|
+
case sub
|
829
|
+
when nil
|
830
|
+
request_tc_with_restarted_threads [:show, :default, pat] # something useful
|
831
|
+
when :locals
|
832
|
+
request_tc_with_restarted_threads [:show, :locals, pat]
|
833
|
+
when :ivars
|
834
|
+
request_tc_with_restarted_threads [:show, :ivars, pat, opt]
|
835
|
+
when :consts
|
836
|
+
request_tc_with_restarted_threads [:show, :consts, pat, opt]
|
837
|
+
when :globals
|
838
|
+
request_tc_with_restarted_threads [:show, :globals, pat]
|
839
|
+
when :threads
|
840
|
+
thread_list
|
841
|
+
:retry
|
842
|
+
when :breaks, :watchs
|
843
|
+
show_bps
|
844
|
+
:retry
|
845
|
+
else
|
846
|
+
@ui.puts "unrecognized argument for info command: #{arg}"
|
847
|
+
show_help 'info'
|
848
|
+
:retry
|
849
|
+
end
|
850
|
+
end
|
851
|
+
|
852
|
+
# * `o[utline]` or `ls`
|
853
|
+
# * Show you available methods, constants, local variables, and instance variables in the current scope.
|
854
|
+
# * `o[utline] <expr>` or `ls <expr>`
|
855
|
+
# * Show you available methods and instance variables of the given object.
|
856
|
+
# * If the object is a class/module, it also lists its constants.
|
857
|
+
register_command 'outline', 'o', 'ls', unsafe: false do |arg|
|
858
|
+
request_tc_with_restarted_threads [:show, :outline, arg]
|
859
|
+
end
|
860
|
+
|
861
|
+
# * `display`
|
862
|
+
# * Show display setting.
|
863
|
+
# * `display <expr>`
|
864
|
+
# * Show the result of `<expr>` at every suspended timing.
|
865
|
+
register_command 'display', postmortem: false do |arg|
|
866
|
+
if arg && !arg.empty?
|
867
|
+
@displays << arg
|
868
|
+
request_eval :try_display, @displays
|
869
|
+
else
|
870
|
+
request_eval :display, @displays
|
871
|
+
end
|
872
|
+
end
|
873
|
+
|
874
|
+
# * `undisplay`
|
875
|
+
# * Remove all display settings.
|
876
|
+
# * `undisplay <displaynum>`
|
877
|
+
# * Remove a specified display setting.
|
878
|
+
register_command 'undisplay', postmortem: false, unsafe: false do |arg|
|
879
|
+
case arg
|
880
|
+
when /(\d+)/
|
881
|
+
if @displays[n = $1.to_i]
|
882
|
+
@displays.delete_at n
|
883
|
+
end
|
884
|
+
request_eval :display, @displays
|
885
|
+
when nil
|
886
|
+
if ask "clear all?", 'N'
|
887
|
+
@displays.clear
|
888
|
+
end
|
889
|
+
:retry
|
890
|
+
end
|
891
|
+
end
|
892
|
+
|
893
|
+
### Frame control
|
894
|
+
|
895
|
+
# * `f[rame]`
|
896
|
+
# * Show the current frame.
|
897
|
+
# * `f[rame] <framenum>`
|
898
|
+
# * Specify a current frame. Evaluation are run on specified frame.
|
899
|
+
register_command 'frame', 'f', unsafe: false do |arg|
|
900
|
+
request_tc [:frame, :set, arg]
|
901
|
+
end
|
902
|
+
|
903
|
+
# * `up`
|
904
|
+
# * Specify the upper frame.
|
905
|
+
register_command 'up', repeat: true, unsafe: false do |arg|
|
906
|
+
request_tc [:frame, :up]
|
907
|
+
end
|
908
|
+
|
909
|
+
# * `down`
|
910
|
+
# * Specify the lower frame.
|
911
|
+
register_command 'down', repeat: true, unsafe: false do |arg|
|
912
|
+
request_tc [:frame, :down]
|
913
|
+
end
|
914
|
+
|
915
|
+
### Evaluate
|
916
|
+
|
917
|
+
# * `p <expr>`
|
918
|
+
# * Evaluate like `p <expr>` on the current frame.
|
919
|
+
register_command 'p' do |arg|
|
920
|
+
request_eval :p, arg.to_s
|
921
|
+
end
|
922
|
+
|
923
|
+
# * `pp <expr>`
|
924
|
+
# * Evaluate like `pp <expr>` on the current frame.
|
925
|
+
register_command 'pp' do |arg|
|
926
|
+
request_eval :pp, arg.to_s
|
927
|
+
end
|
928
|
+
|
929
|
+
# * `eval <expr>`
|
930
|
+
# * Evaluate `<expr>` on the current frame.
|
931
|
+
register_command 'eval', 'call' do |arg|
|
932
|
+
if arg == nil || arg.empty?
|
933
|
+
show_help 'eval'
|
934
|
+
@ui.puts "\nTo evaluate the variable `#{cmd}`, use `pp #{cmd}` instead."
|
935
|
+
:retry
|
936
|
+
else
|
937
|
+
request_eval :call, arg
|
938
|
+
end
|
939
|
+
end
|
940
|
+
|
941
|
+
# * `irb`
|
942
|
+
# * Activate and switch to `irb:rdbg` console
|
943
|
+
register_command 'irb' do |arg|
|
944
|
+
if @ui.remote?
|
945
|
+
@ui.puts "\nIRB is not supported on the remote console."
|
946
|
+
else
|
947
|
+
config_set :irb_console, true
|
948
|
+
end
|
949
|
+
|
950
|
+
:retry
|
951
|
+
end
|
952
|
+
|
953
|
+
### Trace
|
954
|
+
# * `trace`
|
955
|
+
# * Show available tracers list.
|
956
|
+
# * `trace line`
|
957
|
+
# * Add a line tracer. It indicates line events.
|
958
|
+
# * `trace call`
|
959
|
+
# * Add a call tracer. It indicate call/return events.
|
960
|
+
# * `trace exception`
|
961
|
+
# * Add an exception tracer. It indicates raising exceptions.
|
962
|
+
# * `trace object <expr>`
|
963
|
+
# * Add an object tracer. It indicates that an object by `<expr>` is passed as a parameter or a receiver on method call.
|
964
|
+
# * `trace ... /regexp/`
|
965
|
+
# * Indicates only matched events to `/regexp/`.
|
966
|
+
# * `trace ... into: <file>`
|
967
|
+
# * Save trace information into: `<file>`.
|
968
|
+
# * `trace off <num>`
|
969
|
+
# * Disable tracer specified by `<num>` (use `trace` command to check the numbers).
|
970
|
+
# * `trace off [line|call|pass]`
|
971
|
+
# * Disable all tracers. If `<type>` is provided, disable specified type tracers.
|
972
|
+
register_command 'trace', postmortem: false, unsafe: false do |arg|
|
973
|
+
if (re = /\s+into:\s*(.+)/) =~ arg
|
974
|
+
into = $1
|
975
|
+
arg.sub!(re, '')
|
976
|
+
end
|
977
|
+
|
978
|
+
if (re = /\s\/(.+)\/\z/) =~ arg
|
979
|
+
pattern = $1
|
980
|
+
arg.sub!(re, '')
|
981
|
+
end
|
982
|
+
|
983
|
+
case arg
|
984
|
+
when nil
|
985
|
+
@ui.puts 'Tracers:'
|
986
|
+
@tracers.values.each_with_index{|t, i|
|
987
|
+
@ui.puts "* \##{i} #{t}"
|
988
|
+
}
|
989
|
+
@ui.puts
|
990
|
+
:retry
|
991
|
+
|
992
|
+
when /\Aline\z/
|
993
|
+
add_tracer LineTracer.new(@ui, pattern: pattern, into: into)
|
994
|
+
:retry
|
995
|
+
|
996
|
+
when /\Acall\z/
|
997
|
+
add_tracer CallTracer.new(@ui, pattern: pattern, into: into)
|
998
|
+
:retry
|
999
|
+
|
1000
|
+
when /\Aexception\z/
|
1001
|
+
add_tracer ExceptionTracer.new(@ui, pattern: pattern, into: into)
|
1002
|
+
:retry
|
1003
|
+
|
1004
|
+
when /\Aobject\s+(.+)/
|
1005
|
+
request_tc_with_restarted_threads [:trace, :object, $1.strip, {pattern: pattern, into: into}]
|
1006
|
+
|
1007
|
+
when /\Aoff\s+(\d+)\z/
|
1008
|
+
if t = @tracers.values[$1.to_i]
|
1009
|
+
t.disable
|
1010
|
+
@ui.puts "Disable #{t.to_s}"
|
1011
|
+
else
|
1012
|
+
@ui.puts "Unmatched: #{$1}"
|
1013
|
+
end
|
1014
|
+
:retry
|
1015
|
+
|
1016
|
+
when /\Aoff(\s+(line|call|exception|object))?\z/
|
1017
|
+
@tracers.values.each{|t|
|
1018
|
+
if $2.nil? || t.type == $2
|
1019
|
+
t.disable
|
1020
|
+
@ui.puts "Disable #{t.to_s}"
|
1021
|
+
end
|
1022
|
+
}
|
1023
|
+
:retry
|
1024
|
+
|
1025
|
+
else
|
1026
|
+
@ui.puts "Unknown trace option: #{arg.inspect}"
|
1027
|
+
:retry
|
1028
|
+
end
|
1029
|
+
end
|
1030
|
+
|
1031
|
+
# Record
|
1032
|
+
# * `record`
|
1033
|
+
# * Show recording status.
|
1034
|
+
# * `record [on|off]`
|
1035
|
+
# * Start/Stop recording.
|
1036
|
+
# * `step back`
|
1037
|
+
# * Start replay. Step back with the last execution log.
|
1038
|
+
# * `s[tep]` does stepping forward with the last log.
|
1039
|
+
# * `step reset`
|
1040
|
+
# * Stop replay .
|
1041
|
+
register_command 'record', postmortem: false, unsafe: false do |arg|
|
1042
|
+
case arg
|
1043
|
+
when nil, 'on', 'off'
|
1044
|
+
request_tc [:record, arg&.to_sym]
|
1045
|
+
else
|
1046
|
+
@ui.puts "unknown command: #{arg}"
|
1047
|
+
:retry
|
1048
|
+
end
|
1049
|
+
end
|
1050
|
+
|
1051
|
+
### Thread control
|
1052
|
+
|
1053
|
+
# * `th[read]`
|
1054
|
+
# * Show all threads.
|
1055
|
+
# * `th[read] <thnum>`
|
1056
|
+
# * Switch thread specified by `<thnum>`.
|
1057
|
+
register_command 'th', 'thread', unsafe: false do |arg|
|
1058
|
+
case arg
|
1059
|
+
when nil, 'list', 'l'
|
1060
|
+
thread_list
|
1061
|
+
when /(\d+)/
|
1062
|
+
switch_thread $1.to_i
|
1063
|
+
else
|
1064
|
+
@ui.puts "unknown thread command: #{arg}"
|
1065
|
+
end
|
1066
|
+
:retry
|
1067
|
+
end
|
1068
|
+
|
1069
|
+
### Configuration
|
1070
|
+
# * `config`
|
1071
|
+
# * Show all configuration with description.
|
1072
|
+
# * `config <name>`
|
1073
|
+
# * Show current configuration of <name>.
|
1074
|
+
# * `config set <name> <val>` or `config <name> = <val>`
|
1075
|
+
# * Set <name> to <val>.
|
1076
|
+
# * `config append <name> <val>` or `config <name> << <val>`
|
1077
|
+
# * Append `<val>` to `<name>` if it is an array.
|
1078
|
+
# * `config unset <name>`
|
1079
|
+
# * Set <name> to default.
|
1080
|
+
register_command 'config', unsafe: false do |arg|
|
1081
|
+
config_command arg
|
1082
|
+
:retry
|
1083
|
+
end
|
1084
|
+
|
1085
|
+
# * `source <file>`
|
1086
|
+
# * Evaluate lines in `<file>` as debug commands.
|
1087
|
+
register_command 'source' do |arg|
|
1088
|
+
if arg
|
1089
|
+
begin
|
1090
|
+
cmds = File.readlines(path = File.expand_path(arg))
|
1091
|
+
add_preset_commands path, cmds, kick: true, continue: false
|
1092
|
+
rescue Errno::ENOENT
|
1093
|
+
@ui.puts "File not found: #{arg}"
|
1094
|
+
end
|
1095
|
+
else
|
1096
|
+
show_help 'source'
|
1097
|
+
end
|
1098
|
+
:retry
|
1099
|
+
end
|
1100
|
+
|
1101
|
+
# * `open`
|
1102
|
+
# * open debuggee port on UNIX domain socket and wait for attaching.
|
1103
|
+
# * Note that `open` command is EXPERIMENTAL.
|
1104
|
+
# * `open [<host>:]<port>`
|
1105
|
+
# * open debuggee port on TCP/IP with given `[<host>:]<port>` and wait for attaching.
|
1106
|
+
# * `open vscode`
|
1107
|
+
# * open debuggee port for VSCode and launch VSCode if available.
|
1108
|
+
# * `open chrome`
|
1109
|
+
# * open debuggee port for Chrome and wait for attaching.
|
1110
|
+
register_command 'open' do |arg|
|
1111
|
+
case arg&.downcase
|
1112
|
+
when '', nil
|
1113
|
+
::DEBUGGER__.open nonstop: true
|
1114
|
+
when /\A(\d+)z/
|
1115
|
+
::DEBUGGER__.open_tcp host: nil, port: $1.to_i, nonstop: true
|
1116
|
+
when /\A(.+):(\d+)\z/
|
1117
|
+
::DEBUGGER__.open_tcp host: $1, port: $2.to_i, nonstop: true
|
1118
|
+
when 'tcp'
|
1119
|
+
::DEBUGGER__.open_tcp host: CONFIG[:host], port: (CONFIG[:port] || 0), nonstop: true
|
1120
|
+
when 'vscode'
|
1121
|
+
CONFIG[:open] = 'vscode'
|
1122
|
+
::DEBUGGER__.open nonstop: true
|
1123
|
+
when 'chrome', 'cdp'
|
1124
|
+
CONFIG[:open] = 'chrome'
|
1125
|
+
::DEBUGGER__.open_tcp host: CONFIG[:host], port: (CONFIG[:port] || 0), nonstop: true
|
1126
|
+
else
|
1127
|
+
raise "Unknown arg: #{arg}"
|
1128
|
+
end
|
1129
|
+
|
1130
|
+
:retry
|
1131
|
+
end
|
1132
|
+
|
1133
|
+
### Help
|
1134
|
+
|
1135
|
+
# * `h[elp]`
|
1136
|
+
# * Show help for all commands.
|
1137
|
+
# * `h[elp] <command>`
|
1138
|
+
# * Show help for the given command.
|
1139
|
+
register_command 'h', 'help', '?', unsafe: false do |arg|
|
1140
|
+
show_help arg
|
1141
|
+
:retry
|
1142
|
+
end
|
1143
|
+
end
|
1144
|
+
|
1145
|
+
def process_command line
|
1146
|
+
if line.empty?
|
1147
|
+
if @repl_prev_line
|
1148
|
+
line = @repl_prev_line
|
1149
|
+
else
|
1150
|
+
return :retry
|
1151
|
+
end
|
1152
|
+
else
|
1153
|
+
@repl_prev_line = line
|
1154
|
+
end
|
1155
|
+
|
1156
|
+
/([^\s]+)(?:\s+(.+))?/ =~ line
|
1157
|
+
cmd_name, cmd_arg = $1, $2
|
1158
|
+
|
1159
|
+
if cmd = @commands[cmd_name]
|
1160
|
+
check_postmortem if !cmd.postmortem
|
1161
|
+
check_unsafe if cmd.unsafe
|
1162
|
+
cancel_auto_continue if cmd.cancel_auto_continue
|
1163
|
+
@repl_prev_line = nil if !cmd.repeat
|
1164
|
+
|
1165
|
+
cmd.block.call(cmd_arg)
|
1166
|
+
else
|
1167
|
+
@repl_prev_line = nil
|
1168
|
+
check_unsafe
|
1169
|
+
|
1170
|
+
request_eval :pp, line
|
1171
|
+
end
|
1172
|
+
|
1173
|
+
rescue Interrupt
|
1174
|
+
return :retry
|
1175
|
+
rescue SystemExit
|
1176
|
+
raise
|
1177
|
+
rescue PostmortemError => e
|
1178
|
+
@ui.puts e.message
|
1179
|
+
return :retry
|
1180
|
+
rescue Exception => e
|
1181
|
+
@ui.puts "[REPL ERROR] #{e.inspect}"
|
1182
|
+
@ui.puts e.backtrace.map{|e| ' ' + e}
|
1183
|
+
return :retry
|
1184
|
+
end
|
1185
|
+
|
1186
|
+
def step_command type, arg
|
1187
|
+
if type == :until
|
1188
|
+
leave_subsession [:step, type, arg]
|
1189
|
+
return
|
1190
|
+
end
|
1191
|
+
|
1192
|
+
case arg
|
1193
|
+
when nil, /\A\d+\z/
|
1194
|
+
if type == :in && @tc.recorder&.replaying?
|
1195
|
+
request_tc [:step, type, arg&.to_i]
|
1196
|
+
else
|
1197
|
+
leave_subsession [:step, type, arg&.to_i]
|
1198
|
+
end
|
1199
|
+
when /\A(back)\z/, /\A(back)\s+(\d+)\z/, /\A(reset)\z/
|
1200
|
+
if type != :in
|
1201
|
+
@ui.puts "only `step #{arg}` is supported."
|
1202
|
+
:retry
|
1203
|
+
else
|
1204
|
+
type = $1.to_sym
|
1205
|
+
iter = $2&.to_i
|
1206
|
+
request_tc [:step, type, iter]
|
1207
|
+
end
|
1208
|
+
else
|
1209
|
+
@ui.puts "Unknown option: #{arg}"
|
1210
|
+
:retry
|
1211
|
+
end
|
1212
|
+
end
|
1213
|
+
|
1214
|
+
def config_show key
|
1215
|
+
key = key.to_sym
|
1216
|
+
config_detail = CONFIG_SET[key]
|
1217
|
+
|
1218
|
+
if config_detail
|
1219
|
+
v = CONFIG[key]
|
1220
|
+
kv = "#{key} = #{v.inspect}"
|
1221
|
+
desc = config_detail[1]
|
1222
|
+
|
1223
|
+
if config_default = config_detail[3]
|
1224
|
+
desc += " (default: #{config_default})"
|
1225
|
+
end
|
1226
|
+
|
1227
|
+
line = "%-34s \# %s" % [kv, desc]
|
1228
|
+
if line.size > SESSION.width
|
1229
|
+
@ui.puts "\# #{desc}\n#{kv}"
|
1230
|
+
else
|
1231
|
+
@ui.puts line
|
1232
|
+
end
|
1233
|
+
else
|
1234
|
+
@ui.puts "Unknown configuration: #{key}. 'config' shows all configurations."
|
1235
|
+
end
|
1236
|
+
end
|
1237
|
+
|
1238
|
+
def config_set key, val, append: false
|
1239
|
+
if CONFIG_SET[key = key.to_sym]
|
1240
|
+
begin
|
1241
|
+
if append
|
1242
|
+
CONFIG.append_config(key, val)
|
1243
|
+
else
|
1244
|
+
CONFIG[key] = val
|
1245
|
+
end
|
1246
|
+
rescue => e
|
1247
|
+
@ui.puts e.message
|
1248
|
+
end
|
1249
|
+
end
|
1250
|
+
|
1251
|
+
config_show key
|
1252
|
+
end
|
1253
|
+
|
1254
|
+
def config_command arg
|
1255
|
+
case arg
|
1256
|
+
when nil
|
1257
|
+
CONFIG_SET.each do |k, _|
|
1258
|
+
config_show k
|
1259
|
+
end
|
1260
|
+
|
1261
|
+
when /\Aunset\s+(.+)\z/
|
1262
|
+
if CONFIG_SET[key = $1.to_sym]
|
1263
|
+
CONFIG[key] = nil
|
1264
|
+
end
|
1265
|
+
config_show key
|
1266
|
+
|
1267
|
+
when /\A(\w+)\s*=\s*(.+)\z/
|
1268
|
+
config_set $1, $2
|
1269
|
+
|
1270
|
+
when /\A\s*set\s+(\w+)\s+(.+)\z/
|
1271
|
+
config_set $1, $2
|
1272
|
+
|
1273
|
+
when /\A(\w+)\s*<<\s*(.+)\z/
|
1274
|
+
config_set $1, $2, append: true
|
1275
|
+
|
1276
|
+
when /\A\s*append\s+(\w+)\s+(.+)\z/
|
1277
|
+
config_set $1, $2, append: true
|
1278
|
+
|
1279
|
+
when /\A(\w+)\z/
|
1280
|
+
config_show $1
|
1281
|
+
|
1282
|
+
else
|
1283
|
+
@ui.puts "Can not parse parameters: #{arg}"
|
1284
|
+
end
|
1285
|
+
end
|
1286
|
+
|
1287
|
+
|
1288
|
+
def cancel_auto_continue
|
1289
|
+
if @preset_command&.auto_continue
|
1290
|
+
@preset_command.auto_continue = false
|
1291
|
+
end
|
1292
|
+
end
|
1293
|
+
|
1294
|
+
def show_help arg = nil
|
1295
|
+
instructions = (DEBUGGER__.commands.keys + DEBUGGER__.commands.values).uniq
|
1296
|
+
print_instructions = proc do |desc|
|
1297
|
+
desc.split("\n").each do |line|
|
1298
|
+
next if line.start_with?(" ") # workaround for step back
|
1299
|
+
formatted_line = line.gsub(/[\[\]\*]/, "").strip
|
1300
|
+
instructions.each do |inst|
|
1301
|
+
if formatted_line.start_with?("`#{inst}")
|
1302
|
+
desc.sub!(line, colorize(line, [:CYAN, :BOLD]))
|
1303
|
+
end
|
1304
|
+
end
|
1305
|
+
end
|
1306
|
+
@ui.puts desc
|
1307
|
+
end
|
1308
|
+
|
1309
|
+
print_category = proc do |cat|
|
1310
|
+
@ui.puts "\n"
|
1311
|
+
@ui.puts colorize("### #{cat}", [:GREEN, :BOLD])
|
1312
|
+
@ui.puts "\n"
|
1313
|
+
end
|
1314
|
+
|
1315
|
+
DEBUGGER__.helps.each { |cat, cs|
|
1316
|
+
# categories
|
1317
|
+
if arg.nil?
|
1318
|
+
print_category.call(cat)
|
1319
|
+
else
|
1320
|
+
cs.each { |ws, _|
|
1321
|
+
if ws.include?(arg)
|
1322
|
+
print_category.call(cat)
|
1323
|
+
break
|
1324
|
+
end
|
1325
|
+
}
|
1326
|
+
end
|
1327
|
+
|
1328
|
+
# instructions
|
1329
|
+
cs.each { |ws, desc|
|
1330
|
+
if arg.nil? || ws.include?(arg)
|
1331
|
+
print_instructions.call(desc.dup)
|
1332
|
+
return if arg
|
1333
|
+
end
|
1334
|
+
}
|
1335
|
+
}
|
1336
|
+
|
1337
|
+
@ui.puts "not found: #{arg}" if arg
|
1338
|
+
end
|
1339
|
+
|
1340
|
+
def ask msg, default = 'Y'
|
1341
|
+
opts = '[y/n]'.tr(default.downcase, default)
|
1342
|
+
input = @ui.ask("#{msg} #{opts} ")
|
1343
|
+
input = default if input.empty?
|
1344
|
+
case input
|
1345
|
+
when 'y', 'Y'
|
1346
|
+
true
|
1347
|
+
else
|
1348
|
+
false
|
1349
|
+
end
|
1350
|
+
end
|
1351
|
+
|
1352
|
+
# breakpoint management
|
1353
|
+
|
1354
|
+
def iterate_bps
|
1355
|
+
deleted_bps = []
|
1356
|
+
i = 0
|
1357
|
+
@bps.each{|key, bp|
|
1358
|
+
if !bp.deleted?
|
1359
|
+
yield key, bp, i
|
1360
|
+
i += 1
|
1361
|
+
else
|
1362
|
+
deleted_bps << bp
|
1363
|
+
end
|
1364
|
+
}
|
1365
|
+
ensure
|
1366
|
+
deleted_bps.each{|bp| @bps.delete bp}
|
1367
|
+
end
|
1368
|
+
|
1369
|
+
def show_bps specific_bp = nil
|
1370
|
+
iterate_bps do |key, bp, i|
|
1371
|
+
@ui.puts "#%d %s" % [i, bp.to_s] if !specific_bp || bp == specific_bp
|
1372
|
+
end
|
1373
|
+
end
|
1374
|
+
|
1375
|
+
def bp_index specific_bp_key
|
1376
|
+
iterate_bps do |key, bp, i|
|
1377
|
+
if key == specific_bp_key
|
1378
|
+
return [bp, i]
|
1379
|
+
end
|
1380
|
+
end
|
1381
|
+
nil
|
1382
|
+
end
|
1383
|
+
|
1384
|
+
def rehash_bps
|
1385
|
+
bps = @bps.values
|
1386
|
+
@bps.clear
|
1387
|
+
bps.each{|bp|
|
1388
|
+
add_bp bp
|
1389
|
+
}
|
1390
|
+
end
|
1391
|
+
|
1392
|
+
def clean_bps
|
1393
|
+
@bps.delete_if{|_k, bp|
|
1394
|
+
bp.deleted?
|
1395
|
+
}
|
1396
|
+
end
|
1397
|
+
|
1398
|
+
def add_bp bp
|
1399
|
+
# don't repeat commands that add breakpoints
|
1400
|
+
if @bps.has_key? bp.key
|
1401
|
+
if bp.duplicable?
|
1402
|
+
bp
|
1403
|
+
else
|
1404
|
+
@ui.puts "duplicated breakpoint: #{bp}"
|
1405
|
+
bp.disable
|
1406
|
+
nil
|
1407
|
+
end
|
1408
|
+
else
|
1409
|
+
@bps[bp.key] = bp
|
1410
|
+
end
|
1411
|
+
end
|
1412
|
+
|
1413
|
+
def delete_bp arg = nil
|
1414
|
+
case arg
|
1415
|
+
when nil
|
1416
|
+
@bps.each{|key, bp| bp.delete}
|
1417
|
+
@bps.clear
|
1418
|
+
else
|
1419
|
+
del_bp = nil
|
1420
|
+
iterate_bps{|key, bp, i| del_bp = bp if i == arg}
|
1421
|
+
if del_bp
|
1422
|
+
del_bp.delete
|
1423
|
+
@bps.delete del_bp.key
|
1424
|
+
return [arg, del_bp]
|
1425
|
+
end
|
1426
|
+
end
|
1427
|
+
end
|
1428
|
+
|
1429
|
+
BREAK_KEYWORDS = %w(if: do: pre: path:).freeze
|
1430
|
+
|
1431
|
+
private def parse_break type, arg
|
1432
|
+
mode = :sig
|
1433
|
+
expr = Hash.new{|h, k| h[k] = []}
|
1434
|
+
arg.split(' ').each{|w|
|
1435
|
+
if BREAK_KEYWORDS.any?{|pat| w == pat}
|
1436
|
+
mode = w[0..-2].to_sym
|
1437
|
+
else
|
1438
|
+
expr[mode] << w
|
1439
|
+
end
|
1440
|
+
}
|
1441
|
+
expr.default_proc = nil
|
1442
|
+
expr = expr.transform_values{|v| v.join(' ')}
|
1443
|
+
|
1444
|
+
if (path = expr[:path]) && path =~ /\A\/(.*)\/\z/
|
1445
|
+
expr[:path] = Regexp.compile($1)
|
1446
|
+
end
|
1447
|
+
|
1448
|
+
if expr[:do] || expr[:pre]
|
1449
|
+
check_unsafe
|
1450
|
+
expr[:cmd] = [type, expr[:pre], expr[:do]]
|
1451
|
+
end
|
1452
|
+
|
1453
|
+
expr
|
1454
|
+
end
|
1455
|
+
|
1456
|
+
def repl_add_breakpoint arg
|
1457
|
+
expr = parse_break 'break', arg.strip
|
1458
|
+
cond = expr[:if]
|
1459
|
+
cmd = expr[:cmd]
|
1460
|
+
path = expr[:path]
|
1461
|
+
|
1462
|
+
case expr[:sig]
|
1463
|
+
when /\A(\d+)\z/
|
1464
|
+
add_line_breakpoint @tc.location.path, $1.to_i, cond: cond, command: cmd
|
1465
|
+
when /\A(.+)[:\s+](\d+)\z/
|
1466
|
+
add_line_breakpoint $1, $2.to_i, cond: cond, command: cmd
|
1467
|
+
when /\A(.+)([\.\#])(.+)\z/
|
1468
|
+
request_tc [:breakpoint, :method, $1, $2, $3, cond, cmd, path]
|
1469
|
+
return :noretry
|
1470
|
+
when nil
|
1471
|
+
add_check_breakpoint cond, path, cmd
|
1472
|
+
else
|
1473
|
+
@ui.puts "Unknown breakpoint format: #{arg}"
|
1474
|
+
@ui.puts
|
1475
|
+
show_help 'b'
|
1476
|
+
end
|
1477
|
+
end
|
1478
|
+
|
1479
|
+
def repl_add_catch_breakpoint arg
|
1480
|
+
expr = parse_break 'catch', arg.strip
|
1481
|
+
cond = expr[:if]
|
1482
|
+
cmd = expr[:cmd]
|
1483
|
+
path = expr[:path]
|
1484
|
+
|
1485
|
+
bp = CatchBreakpoint.new(expr[:sig], cond: cond, command: cmd, path: path)
|
1486
|
+
add_bp bp
|
1487
|
+
end
|
1488
|
+
|
1489
|
+
def repl_add_watch_breakpoint arg
|
1490
|
+
expr = parse_break 'watch', arg.strip
|
1491
|
+
cond = expr[:if]
|
1492
|
+
cmd = expr[:cmd]
|
1493
|
+
path = Regexp.compile(expr[:path]) if expr[:path]
|
1494
|
+
|
1495
|
+
request_tc [:breakpoint, :watch, expr[:sig], cond, cmd, path]
|
1496
|
+
end
|
1497
|
+
|
1498
|
+
def add_catch_breakpoint pat, cond: nil
|
1499
|
+
bp = CatchBreakpoint.new(pat, cond: cond)
|
1500
|
+
add_bp bp
|
1501
|
+
end
|
1502
|
+
|
1503
|
+
def add_check_breakpoint cond, path, command
|
1504
|
+
bp = CheckBreakpoint.new(cond: cond, path: path, command: command)
|
1505
|
+
add_bp bp
|
1506
|
+
end
|
1507
|
+
|
1508
|
+
def add_line_breakpoint file, line, **kw
|
1509
|
+
file = resolve_path(file)
|
1510
|
+
bp = LineBreakpoint.new(file, line, **kw)
|
1511
|
+
|
1512
|
+
add_bp bp
|
1513
|
+
rescue Errno::ENOENT => e
|
1514
|
+
@ui.puts e.message
|
1515
|
+
end
|
1516
|
+
|
1517
|
+
def clear_breakpoints(&condition)
|
1518
|
+
@bps.delete_if do |k, bp|
|
1519
|
+
if condition.call(k, bp)
|
1520
|
+
bp.delete
|
1521
|
+
true
|
1522
|
+
end
|
1523
|
+
end
|
1524
|
+
end
|
1525
|
+
|
1526
|
+
def clear_line_breakpoints path
|
1527
|
+
path = resolve_path(path)
|
1528
|
+
clear_breakpoints do |k, bp|
|
1529
|
+
bp.is_a?(LineBreakpoint) && bp.path_is?(path)
|
1530
|
+
end
|
1531
|
+
rescue Errno::ENOENT
|
1532
|
+
# just ignore
|
1533
|
+
end
|
1534
|
+
|
1535
|
+
def clear_catch_breakpoints *exception_names
|
1536
|
+
clear_breakpoints do |k, bp|
|
1537
|
+
bp.is_a?(CatchBreakpoint) && exception_names.include?(k[1])
|
1538
|
+
end
|
1539
|
+
end
|
1540
|
+
|
1541
|
+
def clear_all_breakpoints
|
1542
|
+
clear_breakpoints{true}
|
1543
|
+
end
|
1544
|
+
|
1545
|
+
def add_iseq_breakpoint iseq, **kw
|
1546
|
+
bp = ISeqBreakpoint.new(iseq, [:line], **kw)
|
1547
|
+
add_bp bp
|
1548
|
+
end
|
1549
|
+
|
1550
|
+
# tracers
|
1551
|
+
|
1552
|
+
def add_tracer tracer
|
1553
|
+
if @tracers[tracer.key]&.enabled?
|
1554
|
+
tracer.disable
|
1555
|
+
@ui.puts "Duplicated tracer: #{tracer}"
|
1556
|
+
else
|
1557
|
+
@tracers[tracer.key] = tracer
|
1558
|
+
@ui.puts "Enable #{tracer}"
|
1559
|
+
end
|
1560
|
+
end
|
1561
|
+
|
1562
|
+
# threads
|
1563
|
+
|
1564
|
+
def update_thread_list
|
1565
|
+
list = Thread.list
|
1566
|
+
thcs = []
|
1567
|
+
unmanaged = []
|
1568
|
+
|
1569
|
+
list.each{|th|
|
1570
|
+
if thc = @th_clients[th]
|
1571
|
+
if !thc.management?
|
1572
|
+
thcs << thc
|
1573
|
+
end
|
1574
|
+
else
|
1575
|
+
unmanaged << th
|
1576
|
+
end
|
1577
|
+
}
|
1578
|
+
|
1579
|
+
return thcs.sort_by{|thc| thc.id}, unmanaged
|
1580
|
+
end
|
1581
|
+
|
1582
|
+
def thread_list
|
1583
|
+
thcs, unmanaged_ths = update_thread_list
|
1584
|
+
thcs.each_with_index{|thc, i|
|
1585
|
+
@ui.puts "#{@tc == thc ? "--> " : " "}\##{i} #{thc}"
|
1586
|
+
}
|
1587
|
+
|
1588
|
+
if !unmanaged_ths.empty?
|
1589
|
+
@ui.puts "The following threads are not managed yet by the debugger:"
|
1590
|
+
unmanaged_ths.each{|th|
|
1591
|
+
@ui.puts " " + th.to_s
|
1592
|
+
}
|
1593
|
+
end
|
1594
|
+
end
|
1595
|
+
|
1596
|
+
def managed_thread_clients
|
1597
|
+
thcs, _unmanaged_ths = update_thread_list
|
1598
|
+
thcs
|
1599
|
+
end
|
1600
|
+
|
1601
|
+
def switch_thread n
|
1602
|
+
thcs, _unmanaged_ths = update_thread_list
|
1603
|
+
|
1604
|
+
if tc = thcs[n]
|
1605
|
+
if tc.waiting?
|
1606
|
+
@tc = tc
|
1607
|
+
else
|
1608
|
+
@ui.puts "#{tc.thread} is not controllable yet."
|
1609
|
+
end
|
1610
|
+
end
|
1611
|
+
thread_list
|
1612
|
+
end
|
1613
|
+
|
1614
|
+
def setup_threads
|
1615
|
+
prev_clients = @th_clients
|
1616
|
+
@th_clients = {}
|
1617
|
+
|
1618
|
+
Thread.list.each{|th|
|
1619
|
+
if tc = prev_clients[th]
|
1620
|
+
@th_clients[th] = tc
|
1621
|
+
else
|
1622
|
+
create_thread_client(th)
|
1623
|
+
end
|
1624
|
+
}
|
1625
|
+
end
|
1626
|
+
|
1627
|
+
def on_thread_begin th
|
1628
|
+
if @th_clients.has_key? th
|
1629
|
+
# TODO: NG?
|
1630
|
+
else
|
1631
|
+
create_thread_client th
|
1632
|
+
end
|
1633
|
+
end
|
1634
|
+
|
1635
|
+
private def create_thread_client th
|
1636
|
+
# TODO: Ractor support
|
1637
|
+
raise "Only session_server can create thread_client" unless Thread.current == @session_server
|
1638
|
+
@th_clients[th] = ThreadClient.new((@tc_id += 1), @q_evt, Queue.new, th)
|
1639
|
+
end
|
1640
|
+
|
1641
|
+
private def ask_thread_client th
|
1642
|
+
# TODO: Ractor support
|
1643
|
+
q2 = Queue.new
|
1644
|
+
# tc, output, ev, @internal_info, *ev_args = evt
|
1645
|
+
@q_evt << [nil, [], :thread_begin, nil, th, q2]
|
1646
|
+
q2.pop
|
1647
|
+
|
1648
|
+
@th_clients[th] or raise "unexpected error"
|
1649
|
+
end
|
1650
|
+
|
1651
|
+
# can be called by other threads
|
1652
|
+
def get_thread_client th = Thread.current
|
1653
|
+
if @th_clients.has_key? th
|
1654
|
+
@th_clients[th]
|
1655
|
+
else
|
1656
|
+
if Thread.current == @session_server
|
1657
|
+
create_thread_client th
|
1658
|
+
else
|
1659
|
+
ask_thread_client th
|
1660
|
+
end
|
1661
|
+
end
|
1662
|
+
end
|
1663
|
+
|
1664
|
+
private def running_thread_clients_count
|
1665
|
+
@th_clients.count{|th, tc|
|
1666
|
+
next if tc.management?
|
1667
|
+
next unless tc.running?
|
1668
|
+
true
|
1669
|
+
}
|
1670
|
+
end
|
1671
|
+
|
1672
|
+
private def waiting_thread_clients
|
1673
|
+
@th_clients.map{|th, tc|
|
1674
|
+
next if tc.management?
|
1675
|
+
next unless tc.waiting?
|
1676
|
+
tc
|
1677
|
+
}.compact
|
1678
|
+
end
|
1679
|
+
|
1680
|
+
private def thread_stopper
|
1681
|
+
TracePoint.new(:line) do
|
1682
|
+
# run on each thread
|
1683
|
+
tc = ThreadClient.current
|
1684
|
+
next if tc.management?
|
1685
|
+
next unless tc.running?
|
1686
|
+
next if tc == @tc
|
1687
|
+
|
1688
|
+
tc.on_pause
|
1689
|
+
end
|
1690
|
+
end
|
1691
|
+
|
1692
|
+
private def stop_all_threads
|
1693
|
+
return if running_thread_clients_count == 0
|
1694
|
+
|
1695
|
+
stopper = @thread_stopper
|
1696
|
+
stopper.enable unless stopper.enabled?
|
1697
|
+
end
|
1698
|
+
|
1699
|
+
private def restart_all_threads
|
1700
|
+
stopper = @thread_stopper
|
1701
|
+
stopper.disable if stopper.enabled?
|
1702
|
+
|
1703
|
+
waiting_thread_clients.each{|tc|
|
1704
|
+
next if @tc == tc
|
1705
|
+
tc << :continue
|
1706
|
+
}
|
1707
|
+
end
|
1708
|
+
|
1709
|
+
private def enter_subsession
|
1710
|
+
@subsession_id += 1
|
1711
|
+
if !@subsession_stack.empty?
|
1712
|
+
DEBUGGER__.debug{ "Enter subsession (nested #{@subsession_stack.size})" }
|
1713
|
+
else
|
1714
|
+
DEBUGGER__.debug{ "Enter subsession" }
|
1715
|
+
stop_all_threads
|
1716
|
+
@process_group.lock
|
1717
|
+
end
|
1718
|
+
|
1719
|
+
@subsession_stack << true
|
1720
|
+
end
|
1721
|
+
|
1722
|
+
private def leave_subsession type
|
1723
|
+
raise '[BUG] leave_subsession: not entered' if @subsession_stack.empty?
|
1724
|
+
@subsession_stack.pop
|
1725
|
+
|
1726
|
+
if @subsession_stack.empty?
|
1727
|
+
DEBUGGER__.debug{ "Leave subsession" }
|
1728
|
+
@process_group.unlock
|
1729
|
+
restart_all_threads
|
1730
|
+
else
|
1731
|
+
DEBUGGER__.debug{ "Leave subsession (nested #{@subsession_stack.size})" }
|
1732
|
+
end
|
1733
|
+
|
1734
|
+
request_tc type if type
|
1735
|
+
@tc = nil
|
1736
|
+
rescue Exception => e
|
1737
|
+
STDERR.puts PP.pp([e, e.backtrace], ''.dup)
|
1738
|
+
raise
|
1739
|
+
end
|
1740
|
+
|
1741
|
+
def in_subsession?
|
1742
|
+
!@subsession_stack.empty?
|
1743
|
+
end
|
1744
|
+
|
1745
|
+
## event
|
1746
|
+
|
1747
|
+
def on_load iseq, src
|
1748
|
+
DEBUGGER__.info "Load #{iseq.absolute_path || iseq.path}"
|
1749
|
+
|
1750
|
+
file_path, reloaded = @sr.add(iseq, src)
|
1751
|
+
@ui.event :load, file_path, reloaded
|
1752
|
+
|
1753
|
+
# check breakpoints
|
1754
|
+
if file_path
|
1755
|
+
@bps.find_all do |_key, bp|
|
1756
|
+
LineBreakpoint === bp && bp.path_is?(file_path) && (iseq.first_lineno..iseq.last_line).cover?(bp.line)
|
1757
|
+
end.each do |_key, bp|
|
1758
|
+
if !bp.iseq
|
1759
|
+
bp.try_activate iseq
|
1760
|
+
elsif reloaded
|
1761
|
+
@bps.delete bp.key # to allow duplicate
|
1762
|
+
|
1763
|
+
# When we delete a breakpoint from the @bps hash, we also need to deactivate it or else its tracepoint event
|
1764
|
+
# will continue to be enabled and we'll suspend on ghost breakpoints
|
1765
|
+
bp.delete
|
1766
|
+
|
1767
|
+
nbp = LineBreakpoint.copy(bp, iseq)
|
1768
|
+
add_bp nbp
|
1769
|
+
end
|
1770
|
+
end
|
1771
|
+
else # !file_path => file_path is not existing
|
1772
|
+
@bps.find_all do |_key, bp|
|
1773
|
+
LineBreakpoint === bp && !bp.iseq && DEBUGGER__.compare_path(bp.path, (iseq.absolute_path || iseq.path))
|
1774
|
+
end.each do |_key, bp|
|
1775
|
+
bp.try_activate iseq
|
1776
|
+
end
|
1777
|
+
end
|
1778
|
+
end
|
1779
|
+
|
1780
|
+
def resolve_path file
|
1781
|
+
File.realpath(File.expand_path(file))
|
1782
|
+
rescue Errno::ENOENT
|
1783
|
+
case file
|
1784
|
+
when '-e', '-'
|
1785
|
+
return file
|
1786
|
+
else
|
1787
|
+
$LOAD_PATH.each do |lp|
|
1788
|
+
libpath = File.join(lp, file)
|
1789
|
+
return File.realpath(libpath)
|
1790
|
+
rescue Errno::ENOENT
|
1791
|
+
# next
|
1792
|
+
end
|
1793
|
+
end
|
1794
|
+
|
1795
|
+
raise
|
1796
|
+
end
|
1797
|
+
|
1798
|
+
def method_added tp
|
1799
|
+
b = tp.binding
|
1800
|
+
|
1801
|
+
if var_name = b.local_variables.first
|
1802
|
+
mid = b.local_variable_get(var_name)
|
1803
|
+
resolved = true
|
1804
|
+
|
1805
|
+
@bps.each{|k, bp|
|
1806
|
+
case bp
|
1807
|
+
when MethodBreakpoint
|
1808
|
+
if bp.method.nil?
|
1809
|
+
if bp.sig_method_name == mid.to_s
|
1810
|
+
bp.try_enable(added: true)
|
1811
|
+
end
|
1812
|
+
end
|
1813
|
+
|
1814
|
+
resolved = false if !bp.enabled?
|
1815
|
+
end
|
1816
|
+
}
|
1817
|
+
|
1818
|
+
if resolved
|
1819
|
+
Session.deactivate_method_added_trackers
|
1820
|
+
end
|
1821
|
+
|
1822
|
+
case mid
|
1823
|
+
when :method_added, :singleton_method_added
|
1824
|
+
Session.create_method_added_tracker(tp.self, mid)
|
1825
|
+
Session.activate_method_added_trackers unless resolved
|
1826
|
+
end
|
1827
|
+
end
|
1828
|
+
end
|
1829
|
+
|
1830
|
+
class ::Module
|
1831
|
+
undef method_added
|
1832
|
+
def method_added mid; end
|
1833
|
+
end
|
1834
|
+
|
1835
|
+
class ::BasicObject
|
1836
|
+
undef singleton_method_added
|
1837
|
+
def singleton_method_added mid; end
|
1838
|
+
end
|
1839
|
+
|
1840
|
+
def self.create_method_added_tracker mod, method_added_id, method_accessor = :method
|
1841
|
+
m = mod.__send__(method_accessor, method_added_id)
|
1842
|
+
METHOD_ADDED_TRACKERS[m] = TracePoint.new(:call) do |tp|
|
1843
|
+
SESSION.method_added tp
|
1844
|
+
end
|
1845
|
+
end
|
1846
|
+
|
1847
|
+
def self.activate_method_added_trackers
|
1848
|
+
METHOD_ADDED_TRACKERS.each do |m, tp|
|
1849
|
+
tp.enable(target: m) unless tp.enabled?
|
1850
|
+
rescue ArgumentError
|
1851
|
+
DEBUGGER__.warn "Methods defined under #{m.owner} can not track by the debugger."
|
1852
|
+
end
|
1853
|
+
end
|
1854
|
+
|
1855
|
+
def self.deactivate_method_added_trackers
|
1856
|
+
METHOD_ADDED_TRACKERS.each do |m, tp|
|
1857
|
+
tp.disable if tp.enabled?
|
1858
|
+
end
|
1859
|
+
end
|
1860
|
+
|
1861
|
+
METHOD_ADDED_TRACKERS = Hash.new
|
1862
|
+
create_method_added_tracker Module, :method_added, :instance_method
|
1863
|
+
create_method_added_tracker BasicObject, :singleton_method_added, :instance_method
|
1864
|
+
|
1865
|
+
def width
|
1866
|
+
@ui.width
|
1867
|
+
end
|
1868
|
+
|
1869
|
+
def check_postmortem
|
1870
|
+
if @postmortem
|
1871
|
+
raise PostmortemError, "Can not use this command on postmortem mode."
|
1872
|
+
end
|
1873
|
+
end
|
1874
|
+
|
1875
|
+
def check_unsafe
|
1876
|
+
if @unsafe_context
|
1877
|
+
raise RuntimeError, "#{@repl_prev_line.dump} is not allowed on unsafe context."
|
1878
|
+
end
|
1879
|
+
end
|
1880
|
+
|
1881
|
+
def activate_irb_integration
|
1882
|
+
require_relative "irb_integration"
|
1883
|
+
thc = get_thread_client(@session_server)
|
1884
|
+
thc.activate_irb_integration
|
1885
|
+
end
|
1886
|
+
|
1887
|
+
def enter_postmortem_session exc
|
1888
|
+
return unless exc.instance_variable_defined? :@__debugger_postmortem_frames
|
1889
|
+
|
1890
|
+
frames = exc.instance_variable_get(:@__debugger_postmortem_frames)
|
1891
|
+
@postmortem = true
|
1892
|
+
ThreadClient.current.suspend :postmortem, postmortem_frames: frames, postmortem_exc: exc
|
1893
|
+
ensure
|
1894
|
+
@postmortem = false
|
1895
|
+
end
|
1896
|
+
|
1897
|
+
def capture_exception_frames *exclude_path
|
1898
|
+
postmortem_hook = TracePoint.new(:raise){|tp|
|
1899
|
+
exc = tp.raised_exception
|
1900
|
+
frames = DEBUGGER__.capture_frames(__dir__)
|
1901
|
+
|
1902
|
+
exclude_path.each{|ex|
|
1903
|
+
if Regexp === ex
|
1904
|
+
frames.delete_if{|e| ex =~ e.path}
|
1905
|
+
else
|
1906
|
+
frames.delete_if{|e| e.path.start_with? ex.to_s}
|
1907
|
+
end
|
1908
|
+
}
|
1909
|
+
exc.instance_variable_set(:@__debugger_postmortem_frames, frames)
|
1910
|
+
}
|
1911
|
+
postmortem_hook.enable
|
1912
|
+
|
1913
|
+
begin
|
1914
|
+
yield
|
1915
|
+
nil
|
1916
|
+
rescue Exception => e
|
1917
|
+
if e.instance_variable_defined? :@__debugger_postmortem_frames
|
1918
|
+
e
|
1919
|
+
else
|
1920
|
+
raise
|
1921
|
+
end
|
1922
|
+
ensure
|
1923
|
+
postmortem_hook.disable
|
1924
|
+
end
|
1925
|
+
end
|
1926
|
+
|
1927
|
+
def postmortem=(is_enable)
|
1928
|
+
if is_enable
|
1929
|
+
unless @postmortem_hook
|
1930
|
+
@postmortem_hook = TracePoint.new(:raise){|tp|
|
1931
|
+
exc = tp.raised_exception
|
1932
|
+
frames = DEBUGGER__.capture_frames(__dir__)
|
1933
|
+
exc.instance_variable_set(:@__debugger_postmortem_frames, frames)
|
1934
|
+
}
|
1935
|
+
at_exit{
|
1936
|
+
@postmortem_hook.disable
|
1937
|
+
if CONFIG[:postmortem] && (exc = $!) != nil
|
1938
|
+
exc = exc.cause while exc.cause
|
1939
|
+
|
1940
|
+
begin
|
1941
|
+
@ui.puts "Enter postmortem mode with #{exc.inspect}"
|
1942
|
+
@ui.puts exc.backtrace.map{|e| ' ' + e}
|
1943
|
+
@ui.puts "\n"
|
1944
|
+
|
1945
|
+
enter_postmortem_session exc
|
1946
|
+
rescue SystemExit
|
1947
|
+
exit!
|
1948
|
+
rescue Exception => e
|
1949
|
+
@ui = STDERR unless @ui
|
1950
|
+
@ui.puts "Error while postmortem console: #{e.inspect}"
|
1951
|
+
end
|
1952
|
+
end
|
1953
|
+
}
|
1954
|
+
end
|
1955
|
+
|
1956
|
+
if !@postmortem_hook.enabled?
|
1957
|
+
@postmortem_hook.enable
|
1958
|
+
end
|
1959
|
+
else
|
1960
|
+
if @postmortem_hook && @postmortem_hook.enabled?
|
1961
|
+
@postmortem_hook.disable
|
1962
|
+
end
|
1963
|
+
end
|
1964
|
+
end
|
1965
|
+
|
1966
|
+
def set_no_sigint_hook old, new
|
1967
|
+
return unless old != new
|
1968
|
+
return unless @ui.respond_to? :activate_sigint
|
1969
|
+
|
1970
|
+
if old # no -> yes
|
1971
|
+
@ui.activate_sigint
|
1972
|
+
else
|
1973
|
+
@ui.deactivate_sigint
|
1974
|
+
end
|
1975
|
+
end
|
1976
|
+
|
1977
|
+
def save_int_trap cmd
|
1978
|
+
prev, @intercepted_sigint_cmd = @intercepted_sigint_cmd, cmd
|
1979
|
+
prev
|
1980
|
+
end
|
1981
|
+
|
1982
|
+
def intercept_trap_sigint?
|
1983
|
+
@intercept_trap_sigint
|
1984
|
+
end
|
1985
|
+
|
1986
|
+
def intercept_trap_sigint flag, &b
|
1987
|
+
prev = @intercept_trap_sigint
|
1988
|
+
@intercept_trap_sigint = flag
|
1989
|
+
yield
|
1990
|
+
ensure
|
1991
|
+
@intercept_trap_sigint = prev
|
1992
|
+
end
|
1993
|
+
|
1994
|
+
def intercept_trap_sigint_start prev
|
1995
|
+
@intercept_trap_sigint = true
|
1996
|
+
@intercepted_sigint_cmd = prev
|
1997
|
+
end
|
1998
|
+
|
1999
|
+
def intercept_trap_sigint_end
|
2000
|
+
@intercept_trap_sigint = false
|
2001
|
+
prev, @intercepted_sigint_cmd = @intercepted_sigint_cmd, nil
|
2002
|
+
prev
|
2003
|
+
end
|
2004
|
+
|
2005
|
+
def process_info
|
2006
|
+
if @process_group.multi?
|
2007
|
+
"#{$0}\##{Process.pid}"
|
2008
|
+
end
|
2009
|
+
end
|
2010
|
+
|
2011
|
+
def before_fork need_lock = true
|
2012
|
+
if need_lock
|
2013
|
+
@process_group.multi_process!
|
2014
|
+
end
|
2015
|
+
end
|
2016
|
+
|
2017
|
+
def after_fork_parent
|
2018
|
+
@ui.after_fork_parent
|
2019
|
+
end
|
2020
|
+
|
2021
|
+
# experimental API
|
2022
|
+
def extend_feature session: nil, thread_client: nil, ui: nil
|
2023
|
+
Session.include session if session
|
2024
|
+
ThreadClient.include thread_client if thread_client
|
2025
|
+
@ui.extend ui if ui
|
2026
|
+
end
|
2027
|
+
end
|
2028
|
+
|
2029
|
+
class ProcessGroup
|
2030
|
+
def initialize
|
2031
|
+
@lock_file = nil
|
2032
|
+
end
|
2033
|
+
|
2034
|
+
def locked?
|
2035
|
+
true
|
2036
|
+
end
|
2037
|
+
|
2038
|
+
def trylock
|
2039
|
+
true
|
2040
|
+
end
|
2041
|
+
|
2042
|
+
def lock
|
2043
|
+
true
|
2044
|
+
end
|
2045
|
+
|
2046
|
+
def unlock
|
2047
|
+
true
|
2048
|
+
end
|
2049
|
+
|
2050
|
+
def sync
|
2051
|
+
yield
|
2052
|
+
end
|
2053
|
+
|
2054
|
+
def after_fork
|
2055
|
+
end
|
2056
|
+
|
2057
|
+
def multi?
|
2058
|
+
@lock_file
|
2059
|
+
end
|
2060
|
+
|
2061
|
+
def multi_process!
|
2062
|
+
require 'tempfile'
|
2063
|
+
@lock_tempfile = Tempfile.open("ruby-debug-lock-")
|
2064
|
+
@lock_tempfile.close
|
2065
|
+
extend MultiProcessGroup
|
2066
|
+
end
|
2067
|
+
end
|
2068
|
+
|
2069
|
+
module MultiProcessGroup
|
2070
|
+
def multi_process!
|
2071
|
+
end
|
2072
|
+
|
2073
|
+
def after_fork child: true
|
2074
|
+
if child || !@lock_file
|
2075
|
+
@m = Mutex.new unless @m
|
2076
|
+
@m.synchronize do
|
2077
|
+
@lock_level = 0
|
2078
|
+
@lock_file = open(@lock_tempfile.path, 'w')
|
2079
|
+
end
|
2080
|
+
end
|
2081
|
+
end
|
2082
|
+
|
2083
|
+
def info msg
|
2084
|
+
DEBUGGER__.info "#{msg} (#{@lock_level})" # #{caller.first(1).map{|bt| bt.sub(__dir__, '')}}"
|
2085
|
+
end
|
2086
|
+
|
2087
|
+
def locked?
|
2088
|
+
# DEBUGGER__.debug{ "locked? #{@lock_level}" }
|
2089
|
+
@lock_level > 0
|
2090
|
+
end
|
2091
|
+
|
2092
|
+
private def lock_level_up
|
2093
|
+
raise unless @m.owned?
|
2094
|
+
@lock_level += 1
|
2095
|
+
end
|
2096
|
+
|
2097
|
+
private def lock_level_down
|
2098
|
+
raise unless @m.owned?
|
2099
|
+
raise "@lock_level underflow: #{@lock_level}" if @lock_level < 1
|
2100
|
+
@lock_level -= 1
|
2101
|
+
end
|
2102
|
+
|
2103
|
+
private def trylock
|
2104
|
+
@m.synchronize do
|
2105
|
+
if locked?
|
2106
|
+
lock_level_up
|
2107
|
+
info "Try lock, already locked"
|
2108
|
+
true
|
2109
|
+
else
|
2110
|
+
case r = @lock_file.flock(File::LOCK_EX | File::LOCK_NB)
|
2111
|
+
when 0
|
2112
|
+
lock_level_up
|
2113
|
+
info "Try lock with file: success"
|
2114
|
+
true
|
2115
|
+
when false
|
2116
|
+
info "Try lock with file: failed"
|
2117
|
+
false
|
2118
|
+
else
|
2119
|
+
raise "unknown flock result: #{r.inspect}"
|
2120
|
+
end
|
2121
|
+
end
|
2122
|
+
end
|
2123
|
+
end
|
2124
|
+
|
2125
|
+
def lock
|
2126
|
+
unless trylock
|
2127
|
+
@m.synchronize do
|
2128
|
+
if locked?
|
2129
|
+
lock_level_up
|
2130
|
+
else
|
2131
|
+
info "Lock: block"
|
2132
|
+
@lock_file.flock(File::LOCK_EX)
|
2133
|
+
lock_level_up
|
2134
|
+
end
|
2135
|
+
end
|
2136
|
+
|
2137
|
+
info "Lock: success"
|
2138
|
+
end
|
2139
|
+
end
|
2140
|
+
|
2141
|
+
def unlock
|
2142
|
+
@m.synchronize do
|
2143
|
+
raise "lock file is not opened (#{@lock_file.inspect})" if @lock_file.closed?
|
2144
|
+
lock_level_down
|
2145
|
+
@lock_file.flock(File::LOCK_UN) unless locked?
|
2146
|
+
info "Unlocked"
|
2147
|
+
end
|
2148
|
+
end
|
2149
|
+
|
2150
|
+
def sync &b
|
2151
|
+
info "sync"
|
2152
|
+
|
2153
|
+
lock
|
2154
|
+
begin
|
2155
|
+
b.call if b
|
2156
|
+
ensure
|
2157
|
+
unlock
|
2158
|
+
end
|
2159
|
+
end
|
2160
|
+
end
|
2161
|
+
|
2162
|
+
class UI_Base
|
2163
|
+
def event type, *args
|
2164
|
+
case type
|
2165
|
+
when :suspend_bp
|
2166
|
+
i, bp = *args
|
2167
|
+
puts "\nStop by \##{i} #{bp}" if bp
|
2168
|
+
when :suspend_trap
|
2169
|
+
puts "\nStop by #{args.first}"
|
2170
|
+
end
|
2171
|
+
end
|
2172
|
+
|
2173
|
+
def ignore_output_on_suspend?
|
2174
|
+
false
|
2175
|
+
end
|
2176
|
+
|
2177
|
+
def flush
|
2178
|
+
end
|
2179
|
+
end
|
2180
|
+
|
2181
|
+
# manual configuration methods
|
2182
|
+
|
2183
|
+
def self.add_line_breakpoint file, line, **kw
|
2184
|
+
::DEBUGGER__::SESSION.add_line_breakpoint file, line, **kw
|
2185
|
+
end
|
2186
|
+
|
2187
|
+
def self.add_catch_breakpoint pat
|
2188
|
+
::DEBUGGER__::SESSION.add_catch_breakpoint pat
|
2189
|
+
end
|
2190
|
+
|
2191
|
+
# String for requiring location
|
2192
|
+
# nil for -r
|
2193
|
+
def self.require_location
|
2194
|
+
locs = caller_locations
|
2195
|
+
dir_prefix = /#{Regexp.escape(__dir__)}/
|
2196
|
+
|
2197
|
+
locs.each do |loc|
|
2198
|
+
case loc.absolute_path
|
2199
|
+
when dir_prefix
|
2200
|
+
when %r{rubygems/core_ext/kernel_require\.rb}
|
2201
|
+
when %r{bundled_gems\.rb}
|
2202
|
+
else
|
2203
|
+
return loc if loc.absolute_path
|
2204
|
+
end
|
2205
|
+
end
|
2206
|
+
nil
|
2207
|
+
end
|
2208
|
+
|
2209
|
+
# start methods
|
2210
|
+
|
2211
|
+
def self.start nonstop: false, **kw
|
2212
|
+
CONFIG.set_config(**kw)
|
2213
|
+
|
2214
|
+
if CONFIG[:open]
|
2215
|
+
open nonstop: nonstop, **kw
|
2216
|
+
else
|
2217
|
+
unless defined? SESSION
|
2218
|
+
require_relative 'local'
|
2219
|
+
initialize_session{ UI_LocalConsole.new }
|
2220
|
+
end
|
2221
|
+
setup_initial_suspend unless nonstop
|
2222
|
+
end
|
2223
|
+
end
|
2224
|
+
|
2225
|
+
def self.open host: nil, port: CONFIG[:port], sock_path: nil, sock_dir: nil, nonstop: false, **kw
|
2226
|
+
CONFIG.set_config(**kw)
|
2227
|
+
require_relative 'server'
|
2228
|
+
|
2229
|
+
if port || CONFIG[:open] == 'chrome' || (!::Addrinfo.respond_to?(:unix))
|
2230
|
+
open_tcp host: host, port: (port || 0), nonstop: nonstop
|
2231
|
+
else
|
2232
|
+
open_unix sock_path: sock_path, sock_dir: sock_dir, nonstop: nonstop
|
2233
|
+
end
|
2234
|
+
end
|
2235
|
+
|
2236
|
+
def self.open_tcp host: nil, port:, nonstop: false, **kw
|
2237
|
+
CONFIG.set_config(**kw)
|
2238
|
+
require_relative 'server'
|
2239
|
+
|
2240
|
+
if defined? SESSION
|
2241
|
+
SESSION.reset_ui UI_TcpServer.new(host: host, port: port)
|
2242
|
+
else
|
2243
|
+
initialize_session{ UI_TcpServer.new(host: host, port: port) }
|
2244
|
+
end
|
2245
|
+
|
2246
|
+
setup_initial_suspend unless nonstop
|
2247
|
+
end
|
2248
|
+
|
2249
|
+
def self.open_unix sock_path: nil, sock_dir: nil, nonstop: false, **kw
|
2250
|
+
CONFIG.set_config(**kw)
|
2251
|
+
require_relative 'server'
|
2252
|
+
|
2253
|
+
if defined? SESSION
|
2254
|
+
SESSION.reset_ui UI_UnixDomainServer.new(sock_dir: sock_dir, sock_path: sock_path)
|
2255
|
+
else
|
2256
|
+
initialize_session{ UI_UnixDomainServer.new(sock_dir: sock_dir, sock_path: sock_path) }
|
2257
|
+
end
|
2258
|
+
|
2259
|
+
setup_initial_suspend unless nonstop
|
2260
|
+
end
|
2261
|
+
|
2262
|
+
# boot utilities
|
2263
|
+
|
2264
|
+
def self.setup_initial_suspend
|
2265
|
+
if !CONFIG[:nonstop]
|
2266
|
+
case
|
2267
|
+
when CONFIG[:stop_at_load]
|
2268
|
+
add_line_breakpoint __FILE__, __LINE__ + 1, oneshot: true, hook_call: false
|
2269
|
+
nil # stop here
|
2270
|
+
when path = ENV['RUBY_DEBUG_INITIAL_SUSPEND_PATH']
|
2271
|
+
add_line_breakpoint path, 0, oneshot: true, hook_call: false
|
2272
|
+
when loc = ::DEBUGGER__.require_location
|
2273
|
+
# require 'debug/start' or 'debug'
|
2274
|
+
add_line_breakpoint loc.absolute_path, loc.lineno + 1, oneshot: true, hook_call: false
|
2275
|
+
else
|
2276
|
+
# -r
|
2277
|
+
add_line_breakpoint $0, 0, oneshot: true, hook_call: false
|
2278
|
+
end
|
2279
|
+
end
|
2280
|
+
end
|
2281
|
+
|
2282
|
+
class << self
|
2283
|
+
define_method :initialize_session do |&init_ui|
|
2284
|
+
DEBUGGER__.info "Session start (pid: #{Process.pid})"
|
2285
|
+
::DEBUGGER__.const_set(:SESSION, Session.new)
|
2286
|
+
SESSION.activate init_ui.call
|
2287
|
+
load_rc
|
2288
|
+
end
|
2289
|
+
end
|
2290
|
+
|
2291
|
+
# Exiting control
|
2292
|
+
|
2293
|
+
class << self
|
2294
|
+
def skip_all
|
2295
|
+
@skip_all = true
|
2296
|
+
end
|
2297
|
+
|
2298
|
+
def skip?
|
2299
|
+
@skip_all
|
2300
|
+
end
|
2301
|
+
end
|
2302
|
+
|
2303
|
+
def self.load_rc
|
2304
|
+
[[File.expand_path('~/.rdbgrc'), true],
|
2305
|
+
[File.expand_path('~/.rdbgrc.rb'), true],
|
2306
|
+
# ['./.rdbgrc', true], # disable because of security concern
|
2307
|
+
[CONFIG[:init_script], false],
|
2308
|
+
].each{|(path, rc)|
|
2309
|
+
next unless path
|
2310
|
+
next if rc && CONFIG[:no_rc] # ignore rc
|
2311
|
+
|
2312
|
+
if File.file? path
|
2313
|
+
if path.end_with?('.rb')
|
2314
|
+
load path
|
2315
|
+
else
|
2316
|
+
::DEBUGGER__::SESSION.add_preset_commands path, File.readlines(path)
|
2317
|
+
end
|
2318
|
+
elsif !rc
|
2319
|
+
warn "Not found: #{path}"
|
2320
|
+
end
|
2321
|
+
}
|
2322
|
+
|
2323
|
+
# given debug commands
|
2324
|
+
if CONFIG[:commands]
|
2325
|
+
cmds = CONFIG[:commands].split(';;')
|
2326
|
+
::DEBUGGER__::SESSION.add_preset_commands "commands", cmds, kick: false, continue: false
|
2327
|
+
end
|
2328
|
+
end
|
2329
|
+
|
2330
|
+
# Inspector
|
2331
|
+
|
2332
|
+
SHORT_INSPECT_LENGTH = 40
|
2333
|
+
|
2334
|
+
class LimitedPP
|
2335
|
+
def self.pp(obj, max=80)
|
2336
|
+
out = self.new(max)
|
2337
|
+
catch out do
|
2338
|
+
PP.singleline_pp(obj, out)
|
2339
|
+
end
|
2340
|
+
out.buf
|
2341
|
+
end
|
2342
|
+
|
2343
|
+
attr_reader :buf
|
2344
|
+
|
2345
|
+
def initialize max
|
2346
|
+
@max = max
|
2347
|
+
@cnt = 0
|
2348
|
+
@buf = String.new
|
2349
|
+
end
|
2350
|
+
|
2351
|
+
def <<(other)
|
2352
|
+
@buf << other
|
2353
|
+
|
2354
|
+
if @buf.size >= @max
|
2355
|
+
@buf = @buf[0..@max] + '...'
|
2356
|
+
throw self
|
2357
|
+
end
|
2358
|
+
end
|
2359
|
+
end
|
2360
|
+
|
2361
|
+
def self.safe_inspect obj, max_length: SHORT_INSPECT_LENGTH, short: false
|
2362
|
+
if short
|
2363
|
+
LimitedPP.pp(obj, max_length)
|
2364
|
+
else
|
2365
|
+
obj.inspect
|
2366
|
+
end
|
2367
|
+
rescue NoMethodError => e
|
2368
|
+
klass, oid = M_CLASS.bind_call(obj), M_OBJECT_ID.bind_call(obj)
|
2369
|
+
if obj == (r = e.receiver)
|
2370
|
+
"<\##{klass.name}#{oid} does not have \#inspect>"
|
2371
|
+
else
|
2372
|
+
rklass, roid = M_CLASS.bind_call(r), M_OBJECT_ID.bind_call(r)
|
2373
|
+
"<\##{klass.name}:#{roid} contains <\##{rklass}:#{roid} and it does not have #inspect>"
|
2374
|
+
end
|
2375
|
+
rescue Exception => e
|
2376
|
+
"<#inspect raises #{e.inspect}>"
|
2377
|
+
end
|
2378
|
+
|
2379
|
+
def self.warn msg
|
2380
|
+
log :WARN, msg
|
2381
|
+
end
|
2382
|
+
|
2383
|
+
def self.info msg
|
2384
|
+
log :INFO, msg
|
2385
|
+
end
|
2386
|
+
|
2387
|
+
def self.check_loglevel level
|
2388
|
+
lv = LOG_LEVELS[level]
|
2389
|
+
config_lv = LOG_LEVELS[CONFIG[:log_level]]
|
2390
|
+
lv <= config_lv
|
2391
|
+
end
|
2392
|
+
|
2393
|
+
def self.debug(&b)
|
2394
|
+
if check_loglevel :DEBUG
|
2395
|
+
log :DEBUG, b.call
|
2396
|
+
end
|
2397
|
+
end
|
2398
|
+
|
2399
|
+
def self.log level, msg
|
2400
|
+
if check_loglevel level
|
2401
|
+
@logfile = STDERR unless defined? @logfile
|
2402
|
+
return if @logfile.closed?
|
2403
|
+
|
2404
|
+
if defined? SESSION
|
2405
|
+
pi = SESSION.process_info
|
2406
|
+
process_info = pi ? "[#{pi}]" : nil
|
2407
|
+
end
|
2408
|
+
|
2409
|
+
if level == :WARN
|
2410
|
+
# :WARN on debugger is general information
|
2411
|
+
@logfile.puts "DEBUGGER#{process_info}: #{msg}"
|
2412
|
+
@logfile.flush
|
2413
|
+
else
|
2414
|
+
@logfile.puts "DEBUGGER#{process_info} (#{level}): #{msg}"
|
2415
|
+
@logfile.flush
|
2416
|
+
end
|
2417
|
+
end
|
2418
|
+
end
|
2419
|
+
|
2420
|
+
def self.step_in &b
|
2421
|
+
if defined?(SESSION) && SESSION.active?
|
2422
|
+
SESSION.add_iseq_breakpoint RubyVM::InstructionSequence.of(b), oneshot: true
|
2423
|
+
end
|
2424
|
+
|
2425
|
+
yield
|
2426
|
+
end
|
2427
|
+
|
2428
|
+
if File.identical?(__FILE__.upcase, __FILE__.downcase)
|
2429
|
+
# For case insensitive file system (like Windows)
|
2430
|
+
# Note that this check is not enough because case sensitive/insensitive is
|
2431
|
+
# depend on the file system. So this check is only roughly estimation.
|
2432
|
+
|
2433
|
+
def self.compare_path(a, b)
|
2434
|
+
a&.downcase == b&.downcase
|
2435
|
+
end
|
2436
|
+
else
|
2437
|
+
def self.compare_path(a, b)
|
2438
|
+
a == b
|
2439
|
+
end
|
2440
|
+
end
|
2441
|
+
|
2442
|
+
module ForkInterceptor
|
2443
|
+
if Process.respond_to? :_fork
|
2444
|
+
def _fork
|
2445
|
+
return super unless defined?(SESSION) && SESSION.active?
|
2446
|
+
|
2447
|
+
parent_hook, child_hook = __fork_setup_for_debugger
|
2448
|
+
|
2449
|
+
super.tap do |pid|
|
2450
|
+
if pid != 0
|
2451
|
+
# after fork: parent
|
2452
|
+
parent_hook.call pid
|
2453
|
+
else
|
2454
|
+
# after fork: child
|
2455
|
+
child_hook.call
|
2456
|
+
end
|
2457
|
+
end
|
2458
|
+
end
|
2459
|
+
else
|
2460
|
+
def fork(&given_block)
|
2461
|
+
return super unless defined?(SESSION) && SESSION.active?
|
2462
|
+
parent_hook, child_hook = __fork_setup_for_debugger
|
2463
|
+
|
2464
|
+
if given_block
|
2465
|
+
new_block = proc {
|
2466
|
+
# after fork: child
|
2467
|
+
child_hook.call
|
2468
|
+
given_block.call
|
2469
|
+
}
|
2470
|
+
super(&new_block).tap{|pid| parent_hook.call(pid)}
|
2471
|
+
else
|
2472
|
+
super.tap do |pid|
|
2473
|
+
if pid
|
2474
|
+
# after fork: parent
|
2475
|
+
parent_hook.call pid
|
2476
|
+
else
|
2477
|
+
# after fork: child
|
2478
|
+
child_hook.call
|
2479
|
+
end
|
2480
|
+
end
|
2481
|
+
end
|
2482
|
+
end
|
2483
|
+
end
|
2484
|
+
|
2485
|
+
module DaemonInterceptor
|
2486
|
+
def daemon(*args)
|
2487
|
+
return super unless defined?(SESSION) && SESSION.active?
|
2488
|
+
|
2489
|
+
_, child_hook = __fork_setup_for_debugger(:child)
|
2490
|
+
|
2491
|
+
unless SESSION.remote?
|
2492
|
+
DEBUGGER__.warn "Can't debug the code after Process.daemon locally. Use the remote debugging feature."
|
2493
|
+
end
|
2494
|
+
|
2495
|
+
super.tap do
|
2496
|
+
child_hook.call
|
2497
|
+
end
|
2498
|
+
end
|
2499
|
+
end
|
2500
|
+
|
2501
|
+
private def __fork_setup_for_debugger fork_mode = nil
|
2502
|
+
fork_mode ||= CONFIG[:fork_mode]
|
2503
|
+
|
2504
|
+
if fork_mode == :both && CONFIG[:parent_on_fork]
|
2505
|
+
fork_mode = :parent
|
2506
|
+
end
|
2507
|
+
|
2508
|
+
parent_pid = Process.pid
|
2509
|
+
|
2510
|
+
# before fork
|
2511
|
+
case fork_mode
|
2512
|
+
when :parent
|
2513
|
+
parent_hook = -> child_pid {
|
2514
|
+
# Do nothing
|
2515
|
+
}
|
2516
|
+
child_hook = -> {
|
2517
|
+
DEBUGGER__.info "Detaching after fork from child process #{Process.pid}"
|
2518
|
+
SESSION.deactivate
|
2519
|
+
}
|
2520
|
+
when :child
|
2521
|
+
SESSION.before_fork false
|
2522
|
+
|
2523
|
+
parent_hook = -> child_pid {
|
2524
|
+
DEBUGGER__.info "Detaching after fork from parent process #{Process.pid}"
|
2525
|
+
SESSION.after_fork_parent
|
2526
|
+
SESSION.deactivate
|
2527
|
+
}
|
2528
|
+
child_hook = -> {
|
2529
|
+
DEBUGGER__.info "Attaching after process #{parent_pid} fork to child process #{Process.pid}"
|
2530
|
+
SESSION.activate on_fork: true
|
2531
|
+
}
|
2532
|
+
when :both
|
2533
|
+
SESSION.before_fork
|
2534
|
+
|
2535
|
+
parent_hook = -> child_pid {
|
2536
|
+
SESSION.process_group.after_fork
|
2537
|
+
SESSION.after_fork_parent
|
2538
|
+
}
|
2539
|
+
child_hook = -> {
|
2540
|
+
DEBUGGER__.info "Attaching after process #{parent_pid} fork to child process #{Process.pid}"
|
2541
|
+
SESSION.process_group.after_fork child: true
|
2542
|
+
SESSION.activate on_fork: true
|
2543
|
+
}
|
2544
|
+
end
|
2545
|
+
|
2546
|
+
return parent_hook, child_hook
|
2547
|
+
end
|
2548
|
+
end
|
2549
|
+
|
2550
|
+
module TrapInterceptor
|
2551
|
+
def trap sig, *command, &command_proc
|
2552
|
+
sym =
|
2553
|
+
case sig
|
2554
|
+
when String
|
2555
|
+
sig.to_sym
|
2556
|
+
when Integer
|
2557
|
+
Signal.signame(sig)&.to_sym
|
2558
|
+
else
|
2559
|
+
sig
|
2560
|
+
end
|
2561
|
+
|
2562
|
+
case sym
|
2563
|
+
when :INT, :SIGINT
|
2564
|
+
if defined?(SESSION) && SESSION.active? && SESSION.intercept_trap_sigint?
|
2565
|
+
return SESSION.save_int_trap(command.empty? ? command_proc : command.first)
|
2566
|
+
end
|
2567
|
+
end
|
2568
|
+
|
2569
|
+
super
|
2570
|
+
end
|
2571
|
+
end
|
2572
|
+
|
2573
|
+
if Process.respond_to? :_fork
|
2574
|
+
module ::Process
|
2575
|
+
class << self
|
2576
|
+
prepend ForkInterceptor
|
2577
|
+
prepend DaemonInterceptor
|
2578
|
+
end
|
2579
|
+
end
|
2580
|
+
|
2581
|
+
# trap
|
2582
|
+
module ::Kernel
|
2583
|
+
prepend TrapInterceptor
|
2584
|
+
end
|
2585
|
+
module ::Signal
|
2586
|
+
class << self
|
2587
|
+
prepend TrapInterceptor
|
2588
|
+
end
|
2589
|
+
end
|
2590
|
+
else
|
2591
|
+
if RUBY_VERSION >= '3.0.0'
|
2592
|
+
module ::Kernel
|
2593
|
+
prepend ForkInterceptor
|
2594
|
+
prepend TrapInterceptor
|
2595
|
+
end
|
2596
|
+
else
|
2597
|
+
class ::Object
|
2598
|
+
include ForkInterceptor
|
2599
|
+
include TrapInterceptor
|
2600
|
+
end
|
2601
|
+
end
|
2602
|
+
|
2603
|
+
module ::Kernel
|
2604
|
+
class << self
|
2605
|
+
prepend ForkInterceptor
|
2606
|
+
prepend TrapInterceptor
|
2607
|
+
end
|
2608
|
+
end
|
2609
|
+
|
2610
|
+
module ::Process
|
2611
|
+
class << self
|
2612
|
+
prepend ForkInterceptor
|
2613
|
+
prepend DaemonInterceptor
|
2614
|
+
end
|
2615
|
+
end
|
2616
|
+
end
|
2617
|
+
|
2618
|
+
module ::Signal
|
2619
|
+
class << self
|
2620
|
+
prepend TrapInterceptor
|
2621
|
+
end
|
2622
|
+
end
|
2623
|
+
end
|
2624
|
+
|
2625
|
+
module Kernel
|
2626
|
+
def debugger pre: nil, do: nil, up_level: 0
|
2627
|
+
return if !defined?(::DEBUGGER__::SESSION) || !::DEBUGGER__::SESSION.active?
|
2628
|
+
|
2629
|
+
if pre || (do_expr = binding.local_variable_get(:do))
|
2630
|
+
cmds = ['#debugger', pre, do_expr]
|
2631
|
+
end
|
2632
|
+
|
2633
|
+
if ::DEBUGGER__::SESSION.in_subsession?
|
2634
|
+
if cmds
|
2635
|
+
commands = [*cmds[1], *cmds[2]].map{|c| c.split(';;').join("\n")}
|
2636
|
+
::DEBUGGER__::SESSION.add_preset_commands cmds[0], commands, kick: false, continue: false
|
2637
|
+
end
|
2638
|
+
else
|
2639
|
+
loc = caller_locations(up_level, 1).first; ::DEBUGGER__.add_line_breakpoint loc.path, loc.lineno + 1, oneshot: true, command: cmds
|
2640
|
+
end
|
2641
|
+
self
|
2642
|
+
end
|
2643
|
+
|
2644
|
+
alias bb debugger if ENV['RUBY_DEBUG_BB']
|
2645
|
+
end
|
2646
|
+
|
2647
|
+
class Binding
|
2648
|
+
alias break debugger
|
2649
|
+
alias b debugger
|
2650
|
+
end
|
2651
|
+
|
2652
|
+
# for Ruby 2.6 compatibility
|
2653
|
+
unless method(:p).unbind.respond_to? :bind_call
|
2654
|
+
class UnboundMethod
|
2655
|
+
def bind_call(obj, *args)
|
2656
|
+
self.bind(obj).call(*args)
|
2657
|
+
end
|
2658
|
+
end
|
2659
|
+
end
|