Module: Ibex::CLIDiagnostics
- Defined in:
- lib/ibex/cli/diagnostics.rb,
sig/ibex/cli/diagnostics.rbs
Overview
Batch frontend diagnostics subcommand.
Constant Summary collapse
- DIAGNOSTICS_SCHEMA_VERSION =
1- DEFAULT_MAX_DIAGNOSTICS =
20
Instance Method Summary collapse
- #diagnostics_document(result) ⇒ Hash[String, Object?]
- #diagnostics_option_parser(settings) ⇒ OptionParser
- #localized_diagnostic_hash(diagnostic) ⇒ Hash[Symbol, Object?]
- #localized_diagnostic_message(diagnostic) ⇒ String
- #localized_diagnostic_text(diagnostic) ⇒ String
- #positive_diagnostic_limit(value) ⇒ Integer
- #resolution_diagnostic(error, fallback_file) ⇒ Frontend::Diagnostic
-
#resolve_diagnostic_result(result, path, mode) ⇒ Frontend::ParseResult
Cross-file recovery is deliberately bounded to the first resolver error.
- #run_diagnose_command(arguments) ⇒ Integer
- #write_diagnostics(result, format:) ⇒ void
Instance Method Details
#diagnostics_document(result) ⇒ Hash[String, Object?]
107 108 109 110 111 112 113 114 115 |
# File 'lib/ibex/cli/diagnostics.rb', line 107 def diagnostics_document(result) { "ibex_diagnostics" => "frontend", "schema_version" => DIAGNOSTICS_SCHEMA_VERSION, "success" => result.success?, "ast_available" => !result.ast.nil?, "diagnostics" => result.diagnostics.map { |diagnostic| localized_diagnostic_hash(diagnostic) } } end |
#diagnostics_option_parser(settings) ⇒ OptionParser
73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/ibex/cli/diagnostics.rb', line 73 def diagnostics_option_parser(settings) OptionParser.new do || . = "Usage: ibex diagnose [options] grammarfile" .on("--format=FORMAT", %w[text json], "text or json") { |value| settings[:format] = value } .on("--max-diagnostics=N", "positive diagnostic limit") do |value| settings[:max_diagnostics] = positive_diagnostic_limit(value) end .on("--mode=MODE", %w[default extended], "grammar mode") do |value| set_local_configuration_option(settings, :mode, value.to_sym) end .on("--help", "show help") { settings[:help] = true } end end |
#localized_diagnostic_hash(diagnostic) ⇒ Hash[Symbol, Object?]
125 126 127 |
# File 'lib/ibex/cli/diagnostics.rb', line 125 def localized_diagnostic_hash(diagnostic) diagnostic.to_h.merge(message: (diagnostic)) end |
#localized_diagnostic_message(diagnostic) ⇒ String
130 131 132 133 134 |
# File 'lib/ibex/cli/diagnostics.rb', line 130 def (diagnostic) id = "diagnostic.#{diagnostic.code}" id = "diagnostic.generic" unless Messages.known?(id) Messages.translate(id, language: @language, detail: diagnostic.) end |
#localized_diagnostic_text(diagnostic) ⇒ String
118 119 120 121 122 |
# File 'lib/ibex/cli/diagnostics.rb', line 118 def localized_diagnostic_text(diagnostic) return diagnostic.to_s if @language == "en" "#{diagnostic.location}: #{(diagnostic)}" end |
#positive_diagnostic_limit(value) ⇒ Integer
88 89 90 91 92 93 94 95 |
# File 'lib/ibex/cli/diagnostics.rb', line 88 def positive_diagnostic_limit(value) limit = Integer(value, 10) return limit if limit.positive? raise OptionParser::InvalidArgument, "max diagnostics must be positive" rescue ArgumentError raise OptionParser::InvalidArgument, "max diagnostics must be a positive integer" end |
#resolution_diagnostic(error, fallback_file) ⇒ Frontend::Diagnostic
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/ibex/cli/diagnostics.rb', line 56 def resolution_diagnostic(error, fallback_file) match = error..match(/\A(.+):(\d+):(\d+): (.*)\z/m) location = if match Frontend::Location.new( file: match[1].to_s, line: Integer(match[2].to_s), column: Integer(match[3].to_s) ) else Frontend::Location.new(file: fallback_file, line: 1, column: 1) end = match ? match[4].to_s : error. Frontend::Diagnostic.new( code: "frontend.resolution_error", phase: :syntax, message: , location: location, rendered: error. ) end |
#resolve_diagnostic_result(result, path, mode) ⇒ Frontend::ParseResult
Cross-file recovery is deliberately bounded to the first resolver error.
46 47 48 49 50 51 52 53 |
# File 'lib/ibex/cli/diagnostics.rb', line 46 def resolve_diagnostic_result(result, path, mode) Frontend::Resolver.new(path, mode: mode).resolve result rescue Frontend::ResolutionIOError raise rescue Ibex::Error => e Frontend::ParseResult.new(diagnostics: [resolution_diagnostic(e, path)], ast: nil, document: nil) end |
#run_diagnose_command(arguments) ⇒ Integer
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/ibex/cli/diagnostics.rb', line 23 def run_diagnose_command(arguments) settings = { format: "text", max_diagnostics: DEFAULT_MAX_DIAGNOSTICS, mode: Configuration::Registry.fetch("grammar.mode").default, configuration_explicit: [] } #: diagnostic_settings parser = diagnostics_option_parser(settings) remaining = parser.parse(arguments) settings[:mode] = local_configuration_value(settings, "grammar.mode") if settings[:help] @stdout.puts(parser) return 0 end path = input_path(remaining) result = Frontend::Parser.new(File.binread(path), file: path, mode: settings.fetch(:mode)) .parse_with_diagnostics(max_diagnostics: settings.fetch(:max_diagnostics)) result = resolve_diagnostic_result(result, path, settings.fetch(:mode)) if result.success? write_diagnostics(result, format: settings.fetch(:format)) result.success? ? 0 : 1 end |
#write_diagnostics(result, format:) ⇒ void
This method returns an undefined value.
98 99 100 101 102 103 104 |
# File 'lib/ibex/cli/diagnostics.rb', line 98 def write_diagnostics(result, format:) if format == "json" @stdout.puts(JSON.pretty_generate(diagnostics_document(result))) else result.diagnostics.each { |diagnostic| @stdout.puts(localized_diagnostic_text(diagnostic)) } end end |