Module: SimpleCov::ViewCoverage::TemplateCompiler
- Extended by:
- TemplateCompiler
- Included in:
- TemplateCompiler
- Defined in:
- lib/simplecov/view_coverage/template_compiler.rb
Overview
Compiles a single ActionView template: builds a Template for the file on
disk and defines its method into a throwaway module, without ever
rendering it.
Defining the method is the whole trick. Template#compile hands the
handler's generated Ruby to module_eval(source, identifier, offset),
and evaluating a def records the body as executable-but-unexecuted
rather than running it, so Coverage comes away with a zeroed line array
and a full set of branch tuples for the template.
Never compile a template the suite already rendered. Evaluating the same
identifier a second time replaces that file's entry in Coverage rather
than adding to it, so the recompile would zero the hits the run actually
earned and leave a duplicate set of branch tuples behind. ViewCoverage
filters those out before calling here.
Instance Method Summary collapse
-
#available? ⇒ Boolean
False in any project that doesn't load ActionView, which is the common case and not an error: view coverage simply has nothing to do there.
-
#build_template(path, source) ⇒ Object
Nil when nothing is registered for the extension, which is how a default glob naming
.hamlbehaves in a project that has no Haml. -
#call(path) ⇒ Object
Answers whether the compile produced coverage data.
-
#compile_into_throwaway_module(template) ⇒ Object
ActionView keeps
compileprivate, and the module it compiles into is thrown away: what is wanted is the coverage the compile records, not the method it defines. -
#format_for(path) ⇒ Object
The format the template renders, taken from the extension in front of the handler's:
show.html.erbis:html. -
#handler_for(extension) ⇒ Object
Rails main removed
Template.registered_template_handlerwhen the registry moved ontoTemplate::Handlers.
Instance Method Details
#available? ⇒ Boolean
False in any project that doesn't load ActionView, which is the common case and not an error: view coverage simply has nothing to do there.
27 28 29 |
# File 'lib/simplecov/view_coverage/template_compiler.rb', line 27 def available? !defined?(::ActionView::Template).nil? end |
#build_template(path, source) ⇒ Object
Nil when nothing is registered for the extension, which is how a default
glob naming .haml behaves in a project that has no Haml.
handler_for_extension is not that lookup: it falls back to the raw
handler, and the template would report as static text.
71 72 73 74 75 76 77 78 |
# File 'lib/simplecov/view_coverage/template_compiler.rb', line 71 def build_template(path, source) extension = File.extname(path).delete_prefix(".") handler = handler_for(extension) return nil unless handler no_locals = [] #: Array[Symbol] ActionView::Template.new(source, path, handler, locals: no_locals, format: format_for(path)) end |
#call(path) ⇒ Object
Answers whether the compile produced coverage data. A template that doesn't compile can't render either, so the suite has bigger problems than its coverage, but the report is not the place to discover that and a broken view must not take the whole run down.
35 36 37 38 39 40 41 42 43 44 |
# File 'lib/simplecov/view_coverage/template_compiler.rb', line 35 def call(path) template = build_template(path, File.binread(path)) return false unless template compile_into_throwaway_module(template) true rescue StandardError, ScriptError => e warn "[SimpleCov]: Skipping #{path}, which did not compile (#{e.class})" false end |
#compile_into_throwaway_module(template) ⇒ Object
ActionView keeps compile private, and the module it compiles into is
thrown away: what is wanted is the coverage the compile records, not the
method it defines.
mutant:disable -- send and __send__ are the same call.
51 52 53 |
# File 'lib/simplecov/view_coverage/template_compiler.rb', line 51 def compile_into_throwaway_module(template) template.send(:compile, Module.new) end |
#format_for(path) ⇒ Object
The format the template renders, taken from the extension in front of the
handler's: show.html.erb is :html. It reaches the handler's codegen
(an HTML template escapes interpolations, a text one does not), but
never the line structure, so a template named without one compiles fine
as nil.
60 61 62 63 64 65 |
# File 'lib/simplecov/view_coverage/template_compiler.rb', line 60 def format_for(path) segments = File.basename(path).split(".") return nil if segments.length < 3 segments.fetch(-2).to_sym end |
#handler_for(extension) ⇒ Object
Rails main removed Template.registered_template_handler when the
registry moved onto Template::Handlers. Read that hash directly so an
unregistered extension stays nil. Older Rails still have the method.
83 84 85 86 87 88 89 |
# File 'lib/simplecov/view_coverage/template_compiler.rb', line 83 def handler_for(extension) if ActionView::Template.respond_to?(:registered_template_handler) ActionView::Template.registered_template_handler(extension) else ActionView::Template::Handlers.template_handlers[extension.to_sym] end end |