rigortype 0.1.9 → 0.1.11
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/README.md +1 -1
- data/lib/rigor/analysis/baseline.rb +51 -15
- data/lib/rigor/analysis/runner.rb +67 -9
- data/lib/rigor/analysis/worker_session.rb +13 -4
- data/lib/rigor/cache/rbs_descriptor.rb +21 -2
- data/lib/rigor/cache/rbs_environment.rb +2 -1
- data/lib/rigor/cli/annotate_command.rb +57 -7
- data/lib/rigor/cli/baseline_command.rb +4 -3
- data/lib/rigor/cli/coverage_command.rb +126 -0
- data/lib/rigor/cli/coverage_renderer.rb +162 -0
- data/lib/rigor/cli/coverage_report.rb +75 -0
- data/lib/rigor/cli/mcp_command.rb +70 -0
- data/lib/rigor/cli.rb +88 -5
- data/lib/rigor/environment/rbs_loader.rb +46 -5
- data/lib/rigor/environment/reporters.rb +3 -2
- data/lib/rigor/environment.rb +159 -4
- data/lib/rigor/inference/def_return_typer.rb +98 -0
- data/lib/rigor/inference/expression_typer.rb +143 -12
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +5 -0
- data/lib/rigor/inference/method_dispatcher/literal_string_folding.rb +62 -15
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +115 -7
- data/lib/rigor/inference/precision_scanner.rb +131 -0
- data/lib/rigor/inference/statement_evaluator.rb +26 -2
- data/lib/rigor/mcp/loop.rb +43 -0
- data/lib/rigor/mcp/server.rb +263 -0
- data/lib/rigor/mcp.rb +16 -0
- data/lib/rigor/plugin/base.rb +28 -5
- data/lib/rigor/plugin/manifest.rb +33 -5
- data/lib/rigor/plugin/registry.rb +21 -0
- data/lib/rigor/plugin/source_rbs_synthesis_reporter.rb +51 -0
- data/lib/rigor/sig_gen/generator.rb +150 -75
- data/lib/rigor/type/combinator.rb +57 -0
- data/lib/rigor/version.rb +1 -1
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/analyzer.rb +190 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +189 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_index.rb +81 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +142 -0
- data/plugins/rigor-actioncable/lib/rigor-actioncable.rb +3 -0
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/analyzer.rb +178 -0
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +310 -0
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_index.rb +76 -0
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer.rb +177 -0
- data/plugins/rigor-actionmailer/lib/rigor-actionmailer.rb +3 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/analyzer.rb +589 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_discoverer.rb +150 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_index.rb +123 -0
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +247 -0
- data/plugins/rigor-actionpack/lib/rigor-actionpack.rb +3 -0
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/analyzer.rb +114 -0
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +177 -0
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_index.rb +65 -0
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob.rb +117 -0
- data/plugins/rigor-activejob/lib/rigor-activejob.rb +3 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +273 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/inflector.rb +114 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +561 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_index.rb +194 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +240 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_table.rb +94 -0
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +514 -0
- data/plugins/rigor-activerecord/lib/rigor-activerecord.rb +8 -0
- data/plugins/rigor-activerecord/sig/active_record/relation.rbs +182 -0
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/analyzer.rb +78 -0
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_discoverer.rb +162 -0
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_index.rb +43 -0
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage.rb +170 -0
- data/plugins/rigor-activestorage/lib/rigor-activestorage.rb +8 -0
- data/plugins/rigor-activesupport-core-ext/lib/rigor/plugin/activesupport_core_ext.rb +34 -0
- data/plugins/rigor-activesupport-core-ext/lib/rigor-activesupport-core-ext.rb +20 -0
- data/plugins/rigor-activesupport-core-ext/sig/active_support/core_ext.rbs +463 -0
- data/plugins/rigor-devise/lib/rigor/plugin/devise.rb +108 -0
- data/plugins/rigor-devise/lib/rigor-devise.rb +8 -0
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema/schema_scanner.rb +285 -0
- data/plugins/rigor-dry-schema/lib/rigor/plugin/dry_schema.rb +124 -0
- data/plugins/rigor-dry-schema/lib/rigor-dry-schema.rb +8 -0
- data/plugins/rigor-dry-struct/lib/rigor/plugin/dry_struct.rb +116 -0
- data/plugins/rigor-dry-struct/lib/rigor-dry-struct.rb +8 -0
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types/alias_scanner.rb +341 -0
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +120 -0
- data/plugins/rigor-dry-types/lib/rigor-dry-types.rb +8 -0
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation/contract_scanner.rb +120 -0
- data/plugins/rigor-dry-validation/lib/rigor/plugin/dry_validation.rb +85 -0
- data/plugins/rigor-dry-validation/lib/rigor-dry-validation.rb +7 -0
- data/plugins/rigor-dry-validation/sig/dry_validation.rbs +25 -0
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/analyzer.rb +177 -0
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +242 -0
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_index.rb +56 -0
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot.rb +174 -0
- data/plugins/rigor-factorybot/lib/rigor-factorybot.rb +3 -0
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql/type_scanner.rb +409 -0
- data/plugins/rigor-graphql/lib/rigor/plugin/graphql.rb +114 -0
- data/plugins/rigor-graphql/lib/rigor-graphql.rb +8 -0
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami/action_checker.rb +124 -0
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +111 -0
- data/plugins/rigor-hanami/lib/rigor-hanami.rb +3 -0
- data/plugins/rigor-hanami/sig/hanami_action.rbs +78 -0
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest/assertion_analyzer.rb +302 -0
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +72 -0
- data/plugins/rigor-minitest/lib/rigor-minitest.rb +3 -0
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/analyzer.rb +194 -0
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +140 -0
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_index.rb +65 -0
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit.rb +130 -0
- data/plugins/rigor-pundit/lib/rigor-pundit.rb +3 -0
- data/plugins/rigor-rails/lib/rigor-rails.rb +31 -0
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/analyzer.rb +277 -0
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_index.rb +108 -0
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n/locale_loader.rb +138 -0
- data/plugins/rigor-rails-i18n/lib/rigor/plugin/rails_i18n.rb +167 -0
- data/plugins/rigor-rails-i18n/lib/rigor-rails-i18n.rb +3 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/analyzer.rb +161 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_table.rb +103 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +490 -0
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes.rb +158 -0
- data/plugins/rigor-rails-routes/lib/rigor-rails-routes.rb +3 -0
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +163 -0
- data/plugins/rigor-rbs-inline/lib/rigor-rbs-inline.rb +24 -0
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/analyzer.rb +110 -0
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +200 -0
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_type_resolver.rb +170 -0
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/matcher_analyzer.rb +233 -0
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/scope_walker.rb +190 -0
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +188 -0
- data/plugins/rigor-rspec/lib/rigor-rspec.rb +3 -0
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/have_http_status_analyzer.rb +128 -0
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/http_status_codes.rb +60 -0
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails.rb +75 -0
- data/plugins/rigor-rspec-rails/lib/rigor-rspec-rails.rb +3 -0
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers/analyzer.rb +266 -0
- data/plugins/rigor-shoulda-matchers/lib/rigor/plugin/shoulda_matchers.rb +113 -0
- data/plugins/rigor-shoulda-matchers/lib/rigor-shoulda-matchers.rb +3 -0
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/analyzer.rb +152 -0
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_discoverer.rb +190 -0
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_index.rb +61 -0
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq.rb +124 -0
- data/plugins/rigor-sidekiq/lib/rigor-sidekiq.rb +3 -0
- data/plugins/rigor-sinatra/lib/rigor/plugin/sinatra.rb +85 -0
- data/plugins/rigor-sinatra/lib/rigor-sinatra.rb +8 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/absurd_recognizer.rb +108 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/assertion_recognizer.rb +250 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog.rb +95 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +226 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/method_signature.rb +28 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sig_parser.rb +154 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/sigil_detector.rb +100 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/type_translator.rb +323 -0
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +660 -0
- data/plugins/rigor-sorbet/lib/rigor-sorbet.rb +3 -0
- data/plugins/rigor-statesman/lib/rigor/plugin/statesman.rb +209 -0
- data/plugins/rigor-statesman/lib/rigor-statesman.rb +8 -0
- data/plugins/rigor-typescript-utility-types/lib/rigor/plugin/typescript_utility_types.rb +163 -0
- data/plugins/rigor-typescript-utility-types/lib/rigor-typescript-utility-types.rb +9 -0
- data/sig/rigor/analysis/baseline.rbs +39 -0
- data/sig/rigor/environment.rbs +3 -2
- data/sig/rigor/type.rbs +4 -0
- data/sig/rigor.rbs +2 -0
- metadata +180 -1
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rigor/plugin"
|
|
4
|
+
|
|
5
|
+
require_relative "actionmailer/mailer_index"
|
|
6
|
+
require_relative "actionmailer/mailer_discoverer"
|
|
7
|
+
require_relative "actionmailer/analyzer"
|
|
8
|
+
|
|
9
|
+
module Rigor
|
|
10
|
+
module Plugin
|
|
11
|
+
# rigor-actionmailer — validates `Mailer.action(args)`
|
|
12
|
+
# call sites and detects missing view templates.
|
|
13
|
+
#
|
|
14
|
+
# Tier 1C of the [Rails plugins roadmap](../../../../docs/design/20260508-rails-plugins-roadmap.md).
|
|
15
|
+
# Statically discovers mailer classes by walking
|
|
16
|
+
# `mailer_search_paths` and parsing each file with
|
|
17
|
+
# Prism — no `action_mailer` runtime dependency.
|
|
18
|
+
#
|
|
19
|
+
# ## Configuration
|
|
20
|
+
#
|
|
21
|
+
# plugins:
|
|
22
|
+
# - gem: rigor-actionmailer
|
|
23
|
+
# config:
|
|
24
|
+
# mailer_search_paths: ["app/mailers"] # default; optional
|
|
25
|
+
# mailer_base_classes: ["ApplicationMailer", "ActionMailer::Base"] # default; optional
|
|
26
|
+
# views_root: "app/views" # default; optional
|
|
27
|
+
#
|
|
28
|
+
# ## What it checks
|
|
29
|
+
#
|
|
30
|
+
# 1. **Method existence** — `UserMailer.welcome(user)`
|
|
31
|
+
# is flagged when `welcome` is not defined on
|
|
32
|
+
# `UserMailer`.
|
|
33
|
+
# 2. **Argument arity** — calls with too few / too many
|
|
34
|
+
# positional arguments emit `wrong-arity`.
|
|
35
|
+
# 3. **View template existence** — for every action
|
|
36
|
+
# method, at least one of
|
|
37
|
+
# `app/views/<mailer_underscore>/<action>.{html,text}.{erb,haml,slim}`
|
|
38
|
+
# must exist. Missing actions get a `missing-view`
|
|
39
|
+
# diagnostic anchored on the action's `def`.
|
|
40
|
+
#
|
|
41
|
+
# ## Limitations (v0.1.0)
|
|
42
|
+
#
|
|
43
|
+
# - Direct-superclass match only.
|
|
44
|
+
# - Action methods are read from the syntactic instance-
|
|
45
|
+
# side `def` list. `define_method` actions are out of
|
|
46
|
+
# scope.
|
|
47
|
+
# - Adding a brand-new view file does not invalidate the
|
|
48
|
+
# cache until something the mailer file touches
|
|
49
|
+
# changes.
|
|
50
|
+
class Actionmailer < Rigor::Plugin::Base
|
|
51
|
+
manifest(
|
|
52
|
+
id: "actionmailer",
|
|
53
|
+
version: "0.1.0",
|
|
54
|
+
description: "Validates ActionMailer call shape and view template existence.",
|
|
55
|
+
config_schema: {
|
|
56
|
+
"mailer_search_paths" => :array,
|
|
57
|
+
"mailer_base_classes" => :array,
|
|
58
|
+
"views_root" => :string
|
|
59
|
+
}
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
DEFAULT_MAILER_SEARCH_PATHS = ["app/mailers"].freeze
|
|
63
|
+
DEFAULT_MAILER_BASE_CLASSES = %w[ApplicationMailer ActionMailer::Base].freeze
|
|
64
|
+
DEFAULT_VIEWS_ROOT = "app/views"
|
|
65
|
+
|
|
66
|
+
producer :mailer_index do |_params|
|
|
67
|
+
MailerDiscoverer.new(
|
|
68
|
+
io_boundary: io_boundary,
|
|
69
|
+
search_paths: @mailer_search_paths,
|
|
70
|
+
base_classes: @mailer_base_classes,
|
|
71
|
+
views_root: @views_root
|
|
72
|
+
).discover
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def init(_services)
|
|
76
|
+
@mailer_search_paths = Array(config.fetch("mailer_search_paths", DEFAULT_MAILER_SEARCH_PATHS)).map(&:to_s)
|
|
77
|
+
@mailer_base_classes = Array(config.fetch("mailer_base_classes", DEFAULT_MAILER_BASE_CLASSES)).map(&:to_s)
|
|
78
|
+
@views_root = config.fetch("views_root", DEFAULT_VIEWS_ROOT).to_s
|
|
79
|
+
@mailer_index = nil
|
|
80
|
+
@load_error = nil
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def diagnostics_for_file(path:, scope:, root:) # rubocop:disable Lint/UnusedMethodArgument
|
|
84
|
+
index = mailer_index_or_nil
|
|
85
|
+
return [load_error_diagnostic(path)] if index.nil? && @load_error
|
|
86
|
+
return [] if index.nil? || index.empty?
|
|
87
|
+
|
|
88
|
+
diagnostics = []
|
|
89
|
+
diagnostics.concat(call_site_diagnostics(path, root, index))
|
|
90
|
+
diagnostics.concat(missing_view_diagnostics(path, index))
|
|
91
|
+
diagnostics
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
|
|
96
|
+
def mailer_index_or_nil
|
|
97
|
+
return @mailer_index if @mailer_index
|
|
98
|
+
|
|
99
|
+
# Two-glob descriptor: every mailer class under
|
|
100
|
+
# `mailer_search_paths` AND every view template under
|
|
101
|
+
# `views_root`. Without explicit enumeration the cache
|
|
102
|
+
# invalidates only on files the `IoBoundary` has already
|
|
103
|
+
# read in the current process — empty on the first call
|
|
104
|
+
# of a fresh process, so warm hits would serve stale
|
|
105
|
+
# `MailerIndex` data after mailers are added / removed or
|
|
106
|
+
# view templates are added (`view_exists?` failures aren't
|
|
107
|
+
# recorded, so the auto-built descriptor cannot detect a
|
|
108
|
+
# newly-added view).
|
|
109
|
+
mailer_d = glob_descriptor(@mailer_search_paths, "**/*.rb")
|
|
110
|
+
view_d = glob_descriptor([@views_root], "**/*")
|
|
111
|
+
descriptor = Rigor::Cache::Descriptor.compose(mailer_d, view_d)
|
|
112
|
+
@mailer_index = cache_for(:mailer_index, params: {}, descriptor: descriptor).call
|
|
113
|
+
rescue StandardError => e
|
|
114
|
+
@load_error = "rigor-actionmailer: failed to discover mailers: #{e.class}: #{e.message}"
|
|
115
|
+
nil
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def call_site_diagnostics(path, root, index)
|
|
119
|
+
Analyzer.diagnose(path: path, root: root, mailer_index: index).map { |diag| build_diagnostic(diag) }
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Anchors `missing-view` diagnostics on the mailer file
|
|
123
|
+
# itself: when the file currently being analysed is the
|
|
124
|
+
# mailer's source file, emit one diagnostic per missing
|
|
125
|
+
# action template at the action's `def` location.
|
|
126
|
+
def missing_view_diagnostics(path, index)
|
|
127
|
+
canonical = canonical_path(path)
|
|
128
|
+
class_entry = index.find_by_file(canonical)
|
|
129
|
+
return [] if class_entry.nil? || class_entry.missing_views.empty?
|
|
130
|
+
|
|
131
|
+
class_entry.missing_views.map do |action_name|
|
|
132
|
+
action_entry = class_entry.find_action(action_name)
|
|
133
|
+
Rigor::Analysis::Diagnostic.new(
|
|
134
|
+
path: path,
|
|
135
|
+
line: action_entry&.def_line || 1,
|
|
136
|
+
column: action_entry&.def_column || 1,
|
|
137
|
+
severity: :warning,
|
|
138
|
+
rule: "missing-view",
|
|
139
|
+
message: "`#{class_entry.class_name}##{action_name}` has no view template " \
|
|
140
|
+
"under `#{@views_root}/#{underscore(class_entry.class_name.delete_prefix('::'))}/`"
|
|
141
|
+
)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def canonical_path(path)
|
|
146
|
+
File.realpath(path)
|
|
147
|
+
rescue StandardError
|
|
148
|
+
File.expand_path(path)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def underscore(name)
|
|
152
|
+
name.gsub("::", "/")
|
|
153
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
|
154
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
|
155
|
+
.downcase
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def load_error_diagnostic(path)
|
|
159
|
+
Rigor::Analysis::Diagnostic.new(
|
|
160
|
+
path: path, line: 1, column: 1,
|
|
161
|
+
message: @load_error,
|
|
162
|
+
severity: :warning,
|
|
163
|
+
rule: "load-error"
|
|
164
|
+
)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def build_diagnostic(diag)
|
|
168
|
+
Rigor::Analysis::Diagnostic.new(
|
|
169
|
+
path: diag.path, line: diag.line, column: diag.column,
|
|
170
|
+
message: diag.message, severity: diag.severity, rule: diag.rule
|
|
171
|
+
)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
Rigor::Plugin.register(Actionmailer)
|
|
176
|
+
end
|
|
177
|
+
end
|