diecut 0.0.2 → 0.0.3
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/bin/diecut +0 -0
- data/lib/diecut/cli.rb +72 -42
- data/lib/diecut/configurable.rb +4 -2
- data/lib/diecut/context-handler.rb +14 -5
- data/lib/diecut/error-report.rb +58 -0
- data/lib/diecut/errors.rb +70 -1
- data/lib/diecut/linter.rb +14 -131
- data/lib/diecut/mediator.rb +3 -3
- data/lib/diecut/mill.rb +13 -7
- data/lib/diecut/plugin-description.rb +7 -1
- data/lib/diecut/report-builder.rb +114 -0
- data/lib/diecut/report-builders/exception-report.rb +32 -0
- data/lib/diecut/report-builders/invalid-plugin.rb +33 -0
- data/lib/diecut/report-builders/missing-context-field.rb +48 -0
- data/lib/diecut/report-builders/option-collision.rb +49 -0
- data/lib/diecut/report-builders/orphaned-field.rb +63 -0
- data/lib/diecut/report-builders/overridden-context-defaults.rb +62 -0
- data/lib/diecut/report-builders/template-list.rb +38 -0
- data/lib/diecut/report-builders/unused-default.rb +44 -0
- data/lib/diecut/report.rb +11 -1
- data/lib/diecut.rb +6 -0
- data/spec/linter_spec.rb +4 -4
- data/spec/spec_helper.rb +4 -0
- metadata +17 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 107febe45026dd5f8483a22c823ff7df081d9376
|
4
|
+
data.tar.gz: 3ad4f743f9aaa20bbe24a5c72a31d4c1ef813048
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d6837550e1a368a23781bfdd8c0b66450ad3ed19f6d831102cc9b4541285dbdbe4cf45010fa7b767a3babdc29fb78ddff405dfd89d5c5cfa289a5dd6903549f
|
7
|
+
data.tar.gz: 450068202354f5fe74a57f309beeaeb08e11c2eceb4adeb74ca8083d2570679333567d449b616e750146cbf06041d1f363e22f8945b955dff4c5db940c0d4b4d
|
data/bin/diecut
CHANGED
File without changes
|
data/lib/diecut/cli.rb
CHANGED
@@ -3,37 +3,81 @@ require 'diecut'
|
|
3
3
|
require 'diecut/mill'
|
4
4
|
|
5
5
|
module Diecut
|
6
|
-
|
7
|
-
|
6
|
+
module Cli
|
7
|
+
class KindGroup < Thor::Group
|
8
|
+
def self.subclass_for(kind, mediator = nil, example_ui = nil)
|
9
|
+
mediator ||= Diecut.mediator(kind)
|
10
|
+
example_ui ||= mediator.build_example_ui
|
8
11
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
+
Class.new(self) do
|
13
|
+
def self.kind
|
14
|
+
@kind
|
15
|
+
end
|
12
16
|
|
13
|
-
|
14
|
-
|
17
|
+
mediator.plugins.each do |plugin|
|
18
|
+
class_option "with-#{plugin.name}", :default => plugin.default_active?
|
19
|
+
end
|
15
20
|
|
16
|
-
|
17
|
-
|
18
|
-
|
21
|
+
setup_subclass(mediator, example_ui)
|
22
|
+
end.tap do |klass|
|
23
|
+
klass.instance_variable_set("@kind", kind)
|
24
|
+
end
|
25
|
+
end
|
19
26
|
|
20
|
-
|
21
|
-
create_file(path, contents)
|
27
|
+
def self.setup_subclass(mediator, example_ui)
|
22
28
|
end
|
23
29
|
end
|
24
30
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
class Generate < KindGroup
|
32
|
+
include Thor::Actions
|
33
|
+
|
34
|
+
def self.setup_subclass(mediator, example_ui)
|
35
|
+
example_ui.field_names.each do |field|
|
36
|
+
class_option(field, {
|
37
|
+
:desc => example_ui.description(field) || field,
|
38
|
+
:required => example_ui.required?(field),
|
39
|
+
:default => example_ui.default_for(field)
|
40
|
+
})
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def files
|
45
|
+
self.destination_root = target_dir
|
46
|
+
|
47
|
+
mill = Mill.new(self.class.kind)
|
33
48
|
mill.activate_plugins {|name| options["with-#{name}"] }
|
49
|
+
|
50
|
+
ui = mill.user_interface
|
51
|
+
options.delete_if{|_, value| value.nil?}
|
52
|
+
ui.from_hash(options)
|
53
|
+
|
54
|
+
mill.churn(ui) do |path, contents|
|
55
|
+
create_file(path, contents)
|
56
|
+
end
|
34
57
|
end
|
58
|
+
end
|
35
59
|
|
36
|
-
|
60
|
+
class TargetedGenerate < Generate
|
61
|
+
argument :target_dir, :required => true, :type => :string, :banner => "The directory to use as the root of generated output"
|
62
|
+
end
|
63
|
+
|
64
|
+
class Lint < KindGroup
|
65
|
+
class_option :all_on, :default => false, :type => :boolean
|
66
|
+
|
67
|
+
def lint
|
68
|
+
require 'diecut/linter'
|
69
|
+
require 'diecut/error-report'
|
70
|
+
mill = Mill.new(self.class.kind)
|
71
|
+
Diecut.issue_handler = Diecut::ErrorHandling::Reporter.new(mill)
|
72
|
+
|
73
|
+
if options["all_on"]
|
74
|
+
mill.activate_plugins{ true }
|
75
|
+
else
|
76
|
+
mill.activate_plugins{|name| options["with-#{name}"] }
|
77
|
+
end
|
78
|
+
|
79
|
+
puts Linter.new(mill).report
|
80
|
+
end
|
37
81
|
end
|
38
82
|
end
|
39
83
|
|
@@ -42,29 +86,15 @@ module Diecut
|
|
42
86
|
mediator = Diecut.mediator(plugin_kind)
|
43
87
|
example_ui = mediator.build_example_ui
|
44
88
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
@kind = value
|
50
|
-
end
|
51
|
-
@kind
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
mediator.plugins.each do |plugin|
|
56
|
-
class_option "with-#{plugin.name}", :default => plugin.default_active?
|
57
|
-
end
|
89
|
+
Class.new(Thor) do
|
90
|
+
gen = Cli::TargetedGenerate.subclass_for(plugin_kind, mediator, example_ui)
|
91
|
+
method_options(gen.class_options)
|
92
|
+
register gen, "generate", "#{plugin_kind} generate TARGET", "Generate #{plugin_kind} output"
|
58
93
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
end
|
94
|
+
lint = Cli::Lint.subclass_for(plugin_kind, mediator, example_ui)
|
95
|
+
method_options(lint.class_options)
|
96
|
+
register lint, "lint", "#{plugin_kind} lint", "Check well-formed-ness of #{plugin_kind} code generators"
|
63
97
|
end
|
64
|
-
|
65
|
-
klass.kind(plugin_kind)
|
66
|
-
|
67
|
-
klass
|
68
98
|
end
|
69
99
|
|
70
100
|
def self.add_kind(kind)
|
data/lib/diecut/configurable.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'calibrate'
|
2
|
+
require 'diecut/errors'
|
3
|
+
|
2
4
|
module Diecut
|
3
5
|
class Configurable
|
4
6
|
include Calibrate::Configurable
|
@@ -58,14 +60,14 @@ module Diecut
|
|
58
60
|
if from_value.is_a?(Class) and from_value < Calibrate::Configurable
|
59
61
|
into_value.absorb_context(from_value)
|
60
62
|
else
|
61
|
-
raise "
|
63
|
+
raise FieldClash, "#{name.inspect} is already a complex value, but a simple value in the absorbed configurable"
|
62
64
|
end
|
63
65
|
else
|
64
66
|
unless from_value.is_a?(Class) and from_value < Calibrate::Configurable
|
65
67
|
# Noop - maybe should compare the default values? - should always
|
66
68
|
# be nil right now...
|
67
69
|
else
|
68
|
-
raise "
|
70
|
+
raise FieldClash, "#{name.inspect} is already a simple value, but a complex value on the absorbed configurable"
|
69
71
|
end
|
70
72
|
end
|
71
73
|
end
|
@@ -3,12 +3,17 @@ module Diecut
|
|
3
3
|
class ContextHandler
|
4
4
|
attr_accessor :context_class, :ui_class, :plugins
|
5
5
|
|
6
|
+
def issue_handler
|
7
|
+
@issue_handler ||= Diecut.issue_handler
|
8
|
+
end
|
9
|
+
attr_writer :issue_handler
|
10
|
+
|
6
11
|
def apply_simple_defaults
|
7
12
|
plugins.each do |plugin|
|
8
13
|
plugin.context_defaults.each do |default|
|
9
14
|
next unless default.simple?
|
10
15
|
begin
|
11
|
-
apply_simple_default(default)
|
16
|
+
apply_simple_default(plugin, default)
|
12
17
|
rescue Error
|
13
18
|
raise Error, "Plugin #{plugin.name.inspect} failed"
|
14
19
|
end
|
@@ -19,7 +24,7 @@ module Diecut
|
|
19
24
|
def apply_to_ui
|
20
25
|
plugins.each do |plugin|
|
21
26
|
plugin.options.each do |option|
|
22
|
-
apply_option_to_ui(option)
|
27
|
+
apply_option_to_ui(plugin, option)
|
23
28
|
end
|
24
29
|
end
|
25
30
|
end
|
@@ -43,21 +48,25 @@ module Diecut
|
|
43
48
|
end
|
44
49
|
end
|
45
50
|
|
46
|
-
def apply_simple_default(default)
|
51
|
+
def apply_simple_default(plugin, default)
|
47
52
|
target = context_class.walk_path(default.context_path).last
|
48
53
|
if target.metadata.nil?
|
49
|
-
|
54
|
+
issue_handler.unused_default(plugin.name, context_path)
|
50
55
|
else
|
51
56
|
target.metadata.default_value = default.value
|
52
57
|
target.metadata.is(:defaulting)
|
53
58
|
end
|
54
59
|
end
|
55
60
|
|
56
|
-
def apply_option_to_ui(option)
|
61
|
+
def apply_option_to_ui(plugin, option)
|
57
62
|
ui_class.options_hash[option.name] = option
|
58
63
|
|
59
64
|
if option.has_context_path?
|
60
65
|
context_metadata = context_class.walk_path(option.context_path).last.metadata
|
66
|
+
if context_metadata.nil?
|
67
|
+
issue_handler.missing_context_field(plugin.name, option.name, option.context_path)
|
68
|
+
return
|
69
|
+
end
|
61
70
|
if option.has_default?
|
62
71
|
ui_class.setting(option.name, option.default_value)
|
63
72
|
elsif context_metadata.is?(:defaulting)
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'diecut/errors'
|
2
|
+
require 'diecut/report'
|
3
|
+
require 'diecut/report-builders/missing-context-field'
|
4
|
+
require 'diecut/report-builders/unused-default'
|
5
|
+
require 'diecut/report-builders/invalid-plugin'
|
6
|
+
require 'diecut/report-builders/exception-report'
|
7
|
+
|
8
|
+
module Diecut
|
9
|
+
module ErrorHandling
|
10
|
+
class Reporter < Base
|
11
|
+
def initialize(mill)
|
12
|
+
@mill = mill
|
13
|
+
end
|
14
|
+
|
15
|
+
def missing_context_field_report
|
16
|
+
@missing_context_field_report ||= ReportBuilders::MissingContextField.new(@mill)
|
17
|
+
end
|
18
|
+
|
19
|
+
def unused_default_report
|
20
|
+
@unused_default_report ||= ReportBuilders::UnusedDefault.new(@mill)
|
21
|
+
end
|
22
|
+
|
23
|
+
def invalid_plugin_report
|
24
|
+
@invalid_plugin_report ||= ReportBuilders::InvalidPlugin.new(@mill)
|
25
|
+
end
|
26
|
+
|
27
|
+
def exception_report
|
28
|
+
@exception_report ||= ReportBuilders::Exceptions.new(@mill)
|
29
|
+
end
|
30
|
+
|
31
|
+
def missing_context_field(plugin_name, option_name, context_path)
|
32
|
+
missing_context_field_report.add(option_name, context_path, plugin_name)
|
33
|
+
end
|
34
|
+
|
35
|
+
def unused_default(plugin_name, context_path)
|
36
|
+
unused_default_report.add(context_path, plugin_name)
|
37
|
+
end
|
38
|
+
|
39
|
+
def invalid_plugin(name, context_path, value)
|
40
|
+
invalid_plugin_report.add(name, context_path, value)
|
41
|
+
end
|
42
|
+
|
43
|
+
def handle_exception(ex)
|
44
|
+
raise unless ex.is_a? Diecut::Error
|
45
|
+
exception_report.add(ex.class.name, ex.message, (ex.backtrace || [""]).first)
|
46
|
+
end
|
47
|
+
|
48
|
+
def reports
|
49
|
+
[
|
50
|
+
missing_context_field_report.go,
|
51
|
+
unused_default_report.go,
|
52
|
+
invalid_plugin_report.go,
|
53
|
+
exception_report.go
|
54
|
+
]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/diecut/errors.rb
CHANGED
@@ -1,4 +1,71 @@
|
|
1
1
|
module Diecut
|
2
|
+
module ErrorHandling
|
3
|
+
class Base
|
4
|
+
def missing_context_field_message(option_name, context_path)
|
5
|
+
"No template uses a value at #{context_path.inspect}, provided by #{option_name}"
|
6
|
+
end
|
7
|
+
|
8
|
+
def unused_default_message(context_path)
|
9
|
+
"No template uses a value at #{context_path.inspect}, provided as a default"
|
10
|
+
end
|
11
|
+
|
12
|
+
def invalid_plugin_message(name, context_path, value)
|
13
|
+
"Default on #{context_path.inspect} from plugin #{name} has both a simple default value (#{value}) and a dynamic block value, which isn't allowed."
|
14
|
+
end
|
15
|
+
|
16
|
+
def missing_context_field(plugin_name, option_name, context_path)
|
17
|
+
issue(missing_context_field_message(option_name, context_path))
|
18
|
+
end
|
19
|
+
|
20
|
+
def unused_default(plugin_name, context_path)
|
21
|
+
issue(usused_default_message(context_path))
|
22
|
+
end
|
23
|
+
|
24
|
+
def invalid_plugin(name, context_path, value)
|
25
|
+
issue invalid_plugin_message(name, context_path, value)
|
26
|
+
end
|
27
|
+
|
28
|
+
def handle_exception(ex)
|
29
|
+
if Error === ex
|
30
|
+
issue(ex.message)
|
31
|
+
else
|
32
|
+
raise
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Silent < Base
|
38
|
+
def issue(message)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class AllWarn < Base
|
43
|
+
def issue(message)
|
44
|
+
warn message
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class FatalRaise < AllWarn
|
49
|
+
def invalid_plugin(name, context_path, value)
|
50
|
+
raise InvalidPlugin, invalid_plugin_message(name, context_path, value)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class AllRaise < FatalRaise
|
55
|
+
def handle_exception(ex)
|
56
|
+
raise
|
57
|
+
end
|
58
|
+
|
59
|
+
def missing_context_field(option_name, context_path)
|
60
|
+
raise MissingContext, missing_context_field_message(option_name, context_path)
|
61
|
+
end
|
62
|
+
|
63
|
+
def unused_default(context_path)
|
64
|
+
raise UnusedDefault, unused_default_message(context_path)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
2
69
|
class Error < RuntimeError;
|
3
70
|
def message
|
4
71
|
if cause.nil?
|
@@ -9,6 +76,8 @@ module Diecut
|
|
9
76
|
end
|
10
77
|
end
|
11
78
|
class UnusedDefault < Error; end
|
79
|
+
class MissingContext < Error; end
|
12
80
|
class OverriddenDefault < Error; end
|
13
|
-
class
|
81
|
+
class InvalidPlugin < Error; end
|
82
|
+
class FieldClash < Error; end
|
14
83
|
end
|
data/lib/diecut/linter.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
|
-
require 'diecut/report'
|
1
|
+
require 'diecut/report-builder'
|
2
|
+
|
3
|
+
require 'diecut/report-builders/template-list'
|
4
|
+
require 'diecut/report-builders/overridden-context-defaults'
|
5
|
+
require 'diecut/report-builders/option-collision'
|
6
|
+
require 'diecut/report-builders/orphaned-field'
|
2
7
|
|
3
8
|
module Diecut
|
9
|
+
|
4
10
|
class Linter
|
5
11
|
def initialize(mill)
|
6
12
|
@mill = mill
|
@@ -10,12 +16,13 @@ module Diecut
|
|
10
16
|
def report
|
11
17
|
@ui = mill.user_interface
|
12
18
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
+
reports = ReportBuilder.all_kinds.map do |kind|
|
20
|
+
kind.new(mill).go
|
21
|
+
end
|
22
|
+
if Diecut.issue_handler.respond_to?(:reports)
|
23
|
+
reports += Diecut.issue_handler.reports
|
24
|
+
end
|
25
|
+
formatter = ReportFormatter.new( reports)
|
19
26
|
formatter.to_s
|
20
27
|
end
|
21
28
|
|
@@ -49,129 +56,5 @@ module Diecut
|
|
49
56
|
end
|
50
57
|
end
|
51
58
|
end
|
52
|
-
|
53
|
-
def overridden_context_defaults
|
54
|
-
Report.new("Overridden context defaults", ["Output field", "Default value", "Source plugin"]).tap do |report|
|
55
|
-
default_values = Hash.new{|h,k| h[k]=[]}
|
56
|
-
each_default do |default, plugin|
|
57
|
-
next unless default.simple?
|
58
|
-
|
59
|
-
default_values[default.context_path] << [default, plugin]
|
60
|
-
end
|
61
|
-
|
62
|
-
default_values.each do |key, set|
|
63
|
-
default_values[key] = set.find_all do |plugin|
|
64
|
-
!set.any?{|child|
|
65
|
-
next if child == plugin
|
66
|
-
Diecut.plugin_loader.strict_sequence?(plugin[1], child[1])
|
67
|
-
}
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
default_values.each_value do |set|
|
72
|
-
if set.length > 1
|
73
|
-
set.each do |default, plugin|
|
74
|
-
|
75
|
-
report.add(default.context_path.join("."), default.value, plugin.name)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
unless report.empty?
|
81
|
-
report.fail("Multiple plugins assign different values to be rendered")
|
82
|
-
report.advice = unindent(<<-EOA)
|
83
|
-
This is a problem because each plugin may be assuming it's default
|
84
|
-
value, and since there's no guarantee in which order the plugins are
|
85
|
-
loaded, the actual default value is difficult to predict. In general,
|
86
|
-
this kind of override behavior can be difficult to reason about.
|
87
|
-
|
88
|
-
Either the collision is accidental, in which case the default value
|
89
|
-
should be removed from one plugin or the other. If the override is
|
90
|
-
intentional, then the overriding plugin's gem should depend on the
|
91
|
-
overridden one's - since you are overriding the value intentionally,
|
92
|
-
it makes sense to ensure that the value is there to override. Diecut
|
93
|
-
will load plugins such that the dependant plugins are loaded later,
|
94
|
-
which solves the predictability problem.
|
95
|
-
EOA
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
def option_collision_report
|
101
|
-
Report.new("Option collisions", ["Output target", "Option name", "Source plugin"]).tap do |report|
|
102
|
-
option_targets = Hash.new{|h,k| h[k]=[]}
|
103
|
-
each_option do |option, plugin|
|
104
|
-
next unless option.has_context_path?
|
105
|
-
option_targets[option.context_path] << [plugin, option]
|
106
|
-
end
|
107
|
-
option_targets.each_value do |set|
|
108
|
-
if set.length > 1
|
109
|
-
set.each do |plugin, option|
|
110
|
-
report.add(option.context_path.join("."), option.name, plugin.name)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
unless report.empty?
|
116
|
-
report.fail("Multiple options assign the same values to be rendered")
|
117
|
-
report.advice = unindent(<<-EOA)
|
118
|
-
This is problem because two options in the user interface both change
|
119
|
-
rendered values. If a user supplies both with different values, the
|
120
|
-
output isn't predictable (either one might take effect).
|
121
|
-
|
122
|
-
Most likely, this is a simple error: remove options from each group
|
123
|
-
that targets the same rendered value until only one remains. It may
|
124
|
-
also be that one option has a typo - that there's a rendering target
|
125
|
-
that's omitted.
|
126
|
-
EOA
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def orphaned_fields
|
132
|
-
Report.new("Template fields all have settings", ["Output field", "Source file"]).tap do |report|
|
133
|
-
context_class = mill.context_class
|
134
|
-
|
135
|
-
required_fields = {}
|
136
|
-
|
137
|
-
context_class.field_names.each do |field_name|
|
138
|
-
if context_class.field_metadata(field_name).is?(:required)
|
139
|
-
required_fields[field_name.to_s] = []
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
mill.templates.all_templates.each do |template|
|
144
|
-
template.reduced.leaf_fields.each do |field|
|
145
|
-
field = field.join(".")
|
146
|
-
if required_fields.has_key?(field)
|
147
|
-
required_fields[field] << template.path
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
each_option do |option, plugin|
|
153
|
-
next unless option.has_context_path?
|
154
|
-
field = option.context_path.join(".")
|
155
|
-
required_fields.delete(field)
|
156
|
-
end
|
157
|
-
|
158
|
-
required_fields.each do |name, targets|
|
159
|
-
targets.each do |target|
|
160
|
-
report.add(name, target)
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
unless report.empty?
|
165
|
-
report.status = "WARN"
|
166
|
-
report.advice = unindent(<<-EOA)
|
167
|
-
These fields might not receive a value during generation, which will
|
168
|
-
raise an error at use time.
|
169
|
-
|
170
|
-
It's possible these fields are set in a resolve block in one of the
|
171
|
-
plugins - Diecut can't check for that yet.
|
172
|
-
EOA
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
59
|
end
|
177
60
|
end
|
data/lib/diecut/mediator.rb
CHANGED
@@ -40,10 +40,10 @@ module Diecut
|
|
40
40
|
# < User gets involved >
|
41
41
|
#
|
42
42
|
def build_example_ui
|
43
|
-
ui_class =
|
43
|
+
ui_class = UIConfig.build_subclass("Example UI")
|
44
44
|
|
45
45
|
handler = ContextHandler.new
|
46
|
-
handler.context_class =
|
46
|
+
handler.context_class = Configurable.build_subclass("dummy context")
|
47
47
|
handler.ui_class = ui_class
|
48
48
|
handler.plugins = @plugins
|
49
49
|
|
@@ -54,7 +54,7 @@ module Diecut
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def build_ui_class(context_class)
|
57
|
-
ui_class =
|
57
|
+
ui_class = UIConfig.build_subclass("User Interface")
|
58
58
|
|
59
59
|
handler = ContextHandler.new
|
60
60
|
handler.context_class = context_class
|
data/lib/diecut/mill.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'valise'
|
2
2
|
require 'diecut'
|
3
|
+
require 'diecut/errors'
|
3
4
|
require 'diecut/template-set'
|
4
5
|
|
5
6
|
module Diecut
|
@@ -8,7 +9,7 @@ module Diecut
|
|
8
9
|
@kind = kind
|
9
10
|
end
|
10
11
|
attr_reader :kind
|
11
|
-
attr_writer :valise, :mediator, :templates
|
12
|
+
attr_writer :valise, :mediator, :templates, :issue_handler
|
12
13
|
|
13
14
|
def mediator
|
14
15
|
@mediator ||= Diecut.mediator(kind)
|
@@ -29,12 +30,17 @@ module Diecut
|
|
29
30
|
end
|
30
31
|
|
31
32
|
def valise
|
32
|
-
@valise ||=
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
33
|
+
@valise ||=
|
34
|
+
begin
|
35
|
+
stems = mediator.activated_plugins.map do |plugin|
|
36
|
+
plugin.stem_for(kind)
|
37
|
+
end
|
38
|
+
Valise::Set.define do
|
39
|
+
stems.each do |stem|
|
40
|
+
ro stem.template_dir
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
38
44
|
end
|
39
45
|
|
40
46
|
def load_files
|
@@ -22,6 +22,11 @@ module Diecut
|
|
22
22
|
attr_reader :default_activated, :name, :source_path, :context_defaults,
|
23
23
|
:options, :resolve_block
|
24
24
|
|
25
|
+
def issue_handler
|
26
|
+
@issue_handler ||= Diecut.issue_handler
|
27
|
+
end
|
28
|
+
attr_writer :issue_handler
|
29
|
+
|
25
30
|
def kinds
|
26
31
|
@kind_stems.keys
|
27
32
|
end
|
@@ -67,7 +72,7 @@ module Diecut
|
|
67
72
|
#
|
68
73
|
def for_kind(kind, templates = nil, stem = nil)
|
69
74
|
stem ||= [kind]
|
70
|
-
templates ||= "
|
75
|
+
templates ||= "diecut_templates"
|
71
76
|
templates = File.expand_path(templates, File.dirname(caller_locations(1..1).first.absolute_path))
|
72
77
|
@kind_stems[kind] = KindStem.new(kind, stem, templates)
|
73
78
|
end
|
@@ -112,6 +117,7 @@ module Diecut
|
|
112
117
|
[context_path]
|
113
118
|
end
|
114
119
|
if value != NO_VALUE and not block.nil?
|
120
|
+
issue_handler.invalid_plugin(name, context_path, value)
|
115
121
|
raise InvalidPlugin, "Default on #{name.inspect} both has a simple default value (#{value}) and a dynamic block value, which isn't allowed."
|
116
122
|
end
|
117
123
|
@context_defaults << ContextDefault.new(context_path, value, block)
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'diecut/report'
|
2
|
+
|
3
|
+
module Diecut
|
4
|
+
class ReportBuilder
|
5
|
+
def self.all_kinds
|
6
|
+
@all_kinds ||= []
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.register
|
10
|
+
ReportBuilder.all_kinds << self
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(mill)
|
14
|
+
@mill = mill
|
15
|
+
end
|
16
|
+
attr_reader :mill
|
17
|
+
|
18
|
+
def unindent(text)
|
19
|
+
return if text.nil?
|
20
|
+
indent = text.scan(/(^[ \t]*)\S/).map{|cap| cap.first}.max_by(&:length)
|
21
|
+
text.gsub(%r{^#{indent}},'')
|
22
|
+
end
|
23
|
+
|
24
|
+
def each_plugin
|
25
|
+
mill.mediator.activated_plugins.each do |plugin|
|
26
|
+
yield plugin
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def each_default
|
31
|
+
each_plugin do |plugin|
|
32
|
+
plugin.context_defaults.each do |default|
|
33
|
+
yield default, plugin
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def each_option
|
39
|
+
each_plugin do |plugin|
|
40
|
+
plugin.options.each do |option|
|
41
|
+
yield option, plugin
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def each_template
|
47
|
+
mill.templates.templates.each do |name, template|
|
48
|
+
yield name, template
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def report
|
53
|
+
@report ||= build_report
|
54
|
+
end
|
55
|
+
|
56
|
+
def build_report
|
57
|
+
Report.new(report_name, report_fields)
|
58
|
+
end
|
59
|
+
|
60
|
+
def strict_sequence?(first, second)
|
61
|
+
return false if first == second
|
62
|
+
Diecut.plugin_loader.strict_sequence?(first, second)
|
63
|
+
end
|
64
|
+
|
65
|
+
def go
|
66
|
+
collect
|
67
|
+
review
|
68
|
+
report
|
69
|
+
end
|
70
|
+
|
71
|
+
def report_status
|
72
|
+
report.empty? ? 'OK' : 'FAIL'
|
73
|
+
end
|
74
|
+
|
75
|
+
def pass_summary
|
76
|
+
nil
|
77
|
+
end
|
78
|
+
|
79
|
+
def fail_summary
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
|
83
|
+
def other_summary
|
84
|
+
nil
|
85
|
+
end
|
86
|
+
|
87
|
+
def pass_advice
|
88
|
+
nil
|
89
|
+
end
|
90
|
+
|
91
|
+
def fail_advice
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
|
95
|
+
def other_advice
|
96
|
+
nil
|
97
|
+
end
|
98
|
+
|
99
|
+
def review
|
100
|
+
report.status = report_status.to_s.upcase
|
101
|
+
case report.status
|
102
|
+
when "OK", "PASS"
|
103
|
+
report.summary = pass_summary
|
104
|
+
report.advice = unindent(pass_advice)
|
105
|
+
when 'FAIL'
|
106
|
+
report.summary = fail_summary
|
107
|
+
report.advice = unindent(fail_advice)
|
108
|
+
else
|
109
|
+
report.summary = other_summary
|
110
|
+
report.advice = unindent(other_advice)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'diecut/report-builder'
|
2
|
+
|
3
|
+
module Diecut
|
4
|
+
module ReportBuilders
|
5
|
+
class Exceptions < ReportBuilder
|
6
|
+
def report_name
|
7
|
+
"Exceptions raised during definition"
|
8
|
+
end
|
9
|
+
|
10
|
+
def report_fields
|
11
|
+
["Exception class", "message", "source line"]
|
12
|
+
end
|
13
|
+
|
14
|
+
def collect
|
15
|
+
end
|
16
|
+
|
17
|
+
def add(*args)
|
18
|
+
report.add(*args)
|
19
|
+
end
|
20
|
+
|
21
|
+
def fail_summary
|
22
|
+
"Exceptions were raised during the kind definition process"
|
23
|
+
end
|
24
|
+
|
25
|
+
def other_advice
|
26
|
+
<<-EOA
|
27
|
+
Exceptions were raised while defining plugins for generation. Those need to be fixed.
|
28
|
+
EOA
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'diecut/report-builder'
|
2
|
+
|
3
|
+
module Diecut
|
4
|
+
module ReportBuilders
|
5
|
+
class InvalidPlugin < ReportBuilder
|
6
|
+
def report_name
|
7
|
+
"General plugin health"
|
8
|
+
end
|
9
|
+
|
10
|
+
def report_fields
|
11
|
+
["Plugin name", "Problem description"]
|
12
|
+
end
|
13
|
+
|
14
|
+
def collect
|
15
|
+
end
|
16
|
+
|
17
|
+
def add(*args)
|
18
|
+
report.add(*args)
|
19
|
+
end
|
20
|
+
|
21
|
+
def other_summary
|
22
|
+
"There were problems defining plugins"
|
23
|
+
end
|
24
|
+
|
25
|
+
def other_advice
|
26
|
+
<<-EOA
|
27
|
+
The plugins above had unrecoverable issues while being defined. They
|
28
|
+
should be fixed, or not included during generation.
|
29
|
+
EOA
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'diecut/report-builder'
|
2
|
+
|
3
|
+
module Diecut
|
4
|
+
module ReportBuilders
|
5
|
+
class MissingContextField < ReportBuilder
|
6
|
+
def report_name
|
7
|
+
"Unused options"
|
8
|
+
end
|
9
|
+
|
10
|
+
def report_fields
|
11
|
+
["Output field name", "Option_name", "Plugin name"]
|
12
|
+
end
|
13
|
+
|
14
|
+
def report_status
|
15
|
+
report.empty? ? "OK" : "WARN"
|
16
|
+
end
|
17
|
+
|
18
|
+
def collect
|
19
|
+
end
|
20
|
+
|
21
|
+
def add(*args)
|
22
|
+
report.add(*args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def other_summary
|
26
|
+
"Options provide values that aren't used by any template"
|
27
|
+
end
|
28
|
+
|
29
|
+
def other_advice
|
30
|
+
<<-EOA
|
31
|
+
Plugins defined options that go to fields that don't appear in templates.
|
32
|
+
|
33
|
+
It's possible that a plugin defined an option for its templates but they were
|
34
|
+
overridden, so the fields disappeared. Diecut doesn't yet check for
|
35
|
+
that case. In those cases, you can ignore this warning.
|
36
|
+
|
37
|
+
The other possiblity is that the default path has a typo. This is
|
38
|
+
especially likely if there's also a report about a missing output
|
39
|
+
field. The option might be used in a resolve somewhere, so even if it
|
40
|
+
doesn't directly set an output field, it might influence generation
|
41
|
+
that way.
|
42
|
+
|
43
|
+
Do be careful to check this option: the option
|
44
|
+
EOA
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'diecut/report-builder'
|
2
|
+
|
3
|
+
module Diecut
|
4
|
+
module ReportBuilders
|
5
|
+
class OptionCollisions < ReportBuilder
|
6
|
+
register
|
7
|
+
|
8
|
+
def report_name
|
9
|
+
"Option collisions"
|
10
|
+
end
|
11
|
+
|
12
|
+
def report_fields
|
13
|
+
["Output target", "Option name", "Source plugin"]
|
14
|
+
end
|
15
|
+
|
16
|
+
def collect
|
17
|
+
option_targets = Hash.new{|h,k| h[k]=[]}
|
18
|
+
each_option do |option, plugin|
|
19
|
+
next unless option.has_context_path?
|
20
|
+
option_targets[option.context_path] << [plugin, option]
|
21
|
+
end
|
22
|
+
option_targets.each_value do |set|
|
23
|
+
if set.length > 1
|
24
|
+
set.each do |plugin, option|
|
25
|
+
report.add(option.context_path.join("."), option.name, plugin.name)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def fail_summary
|
32
|
+
"Multiple options assign the same values to be rendered"
|
33
|
+
end
|
34
|
+
|
35
|
+
def fail_advice
|
36
|
+
(<<-EOA)
|
37
|
+
This is problem because two options in the user interface both change
|
38
|
+
rendered values. If a user supplies both with different values, the
|
39
|
+
output isn't predictable (either one might take effect).
|
40
|
+
|
41
|
+
Most likely, this is a simple error: remove options from each group
|
42
|
+
that targets the same rendered value until only one remains. It may
|
43
|
+
also be that one option has a typo - that there's a rendering target
|
44
|
+
that's omitted.
|
45
|
+
EOA
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Diecut
|
2
|
+
module ReportBuilders
|
3
|
+
class OrphanedField < ReportBuilder
|
4
|
+
register
|
5
|
+
|
6
|
+
def report_name
|
7
|
+
"Template fields all have settings"
|
8
|
+
end
|
9
|
+
|
10
|
+
def report_fields
|
11
|
+
["Output field", "Source file"]
|
12
|
+
end
|
13
|
+
|
14
|
+
def collect
|
15
|
+
context_class = mill.context_class
|
16
|
+
|
17
|
+
required_fields = {}
|
18
|
+
|
19
|
+
context_class.field_names.each do |field_name|
|
20
|
+
if context_class.field_metadata(field_name).is?(:required)
|
21
|
+
required_fields[field_name.to_s] = []
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
each_template do |name, template|
|
26
|
+
template.reduced.leaf_fields.each do |field|
|
27
|
+
field = field.join(".")
|
28
|
+
if required_fields.has_key?(field)
|
29
|
+
required_fields[field] << template.path
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
each_option do |option, plugin|
|
35
|
+
next unless option.has_context_path?
|
36
|
+
field = option.context_path.join(".")
|
37
|
+
required_fields.delete(field)
|
38
|
+
end
|
39
|
+
|
40
|
+
required_fields.each do |name, targets|
|
41
|
+
targets.each do |target|
|
42
|
+
report.add(name, target)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def report_status
|
48
|
+
report.empty? ? "OK" : "WARN"
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def other_advice
|
53
|
+
<<-EOA
|
54
|
+
These fields might not receive a value during generation, which will
|
55
|
+
raise an error at use time.
|
56
|
+
|
57
|
+
It's possible these fields are set in a resolve block in one of the
|
58
|
+
plugins - Diecut can't check for that yet.
|
59
|
+
EOA
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'diecut/report-builder'
|
2
|
+
|
3
|
+
module Diecut
|
4
|
+
module ReportBuilders
|
5
|
+
class OverriddenContextDefaults < ReportBuilder
|
6
|
+
register
|
7
|
+
|
8
|
+
def report_name
|
9
|
+
"Overridden context defaults"
|
10
|
+
end
|
11
|
+
|
12
|
+
def report_fields
|
13
|
+
["Output field", "Default value", "Source plugin"]
|
14
|
+
end
|
15
|
+
|
16
|
+
def collect
|
17
|
+
default_values = Hash.new{|h,k| h[k]=[]}
|
18
|
+
each_default do |default, plugin|
|
19
|
+
next unless default.simple?
|
20
|
+
|
21
|
+
default_values[default.context_path] << [default, plugin]
|
22
|
+
end
|
23
|
+
|
24
|
+
default_values.each do |key, set|
|
25
|
+
default_values[key] = set.find_all do |plugin|
|
26
|
+
!set.any?{|child| strict_sequence?(plugin[1], child[1]) }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
default_values.each_value do |set|
|
31
|
+
if set.length > 1
|
32
|
+
set.each do |default, plugin|
|
33
|
+
|
34
|
+
report.add(default.context_path.join("."), default.value, plugin.name)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def fail_summary
|
41
|
+
"Multiple plugins assign different values to be rendered by default"
|
42
|
+
end
|
43
|
+
|
44
|
+
def fail_advice
|
45
|
+
(<<-EOA)
|
46
|
+
This is a problem because each plugin may be assuming it's default
|
47
|
+
value, and since there's no guarantee in which order the plugins are
|
48
|
+
loaded, the actual default value is difficult to predict. In general,
|
49
|
+
this kind of override behavior can be difficult to reason about.
|
50
|
+
|
51
|
+
Either the collision is accidental, in which case the default value
|
52
|
+
should be removed from one plugin or the other. If the override is
|
53
|
+
intentional, then the overriding plugin's gem should depend on the
|
54
|
+
overridden one's - since you are overriding the value intentionally,
|
55
|
+
it makes sense to ensure that the value is there to override. Diecut
|
56
|
+
will load plugins such that the dependant plugins are loaded later,
|
57
|
+
which solves the predictability problem.
|
58
|
+
EOA
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'diecut/report-builder'
|
2
|
+
|
3
|
+
module Diecut
|
4
|
+
class TemplateListBuilder < ReportBuilder
|
5
|
+
register
|
6
|
+
|
7
|
+
def report_name
|
8
|
+
"Templates included"
|
9
|
+
end
|
10
|
+
|
11
|
+
def report_fields
|
12
|
+
["Template path"]
|
13
|
+
end
|
14
|
+
|
15
|
+
def collect
|
16
|
+
each_template do |name, template|
|
17
|
+
report.add(template.path)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def report_status
|
22
|
+
report.empty? ? 'FAIL' : 'OK'
|
23
|
+
end
|
24
|
+
|
25
|
+
def fail_summary
|
26
|
+
report.summary = "No templates will render"
|
27
|
+
end
|
28
|
+
|
29
|
+
def fail_advice
|
30
|
+
(<<-EOA)
|
31
|
+
No plugin provides any templates. This is probably simple misconfiguration a plugin, or an important plugin has been omitted.
|
32
|
+
|
33
|
+
Plugins: #{mill.mediator.activated_plugins.map(&:name)}
|
34
|
+
Plugin template paths: #{mill.valise.to_s}
|
35
|
+
EOA
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'diecut/report-builder'
|
2
|
+
|
3
|
+
module Diecut
|
4
|
+
module ReportBuilders
|
5
|
+
class UnusedDefault < ReportBuilder
|
6
|
+
def report_name
|
7
|
+
"Defaults are declared but unused"
|
8
|
+
end
|
9
|
+
|
10
|
+
def report_fields
|
11
|
+
["Output field name", "Plugin name"]
|
12
|
+
end
|
13
|
+
|
14
|
+
def report_status
|
15
|
+
report.empty? ? "OK" : "WARN"
|
16
|
+
end
|
17
|
+
|
18
|
+
def collect
|
19
|
+
end
|
20
|
+
|
21
|
+
def add(*args)
|
22
|
+
report.add(*args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def other_summary
|
26
|
+
"Defaults are defined for fields that don't exist in output templates"
|
27
|
+
end
|
28
|
+
|
29
|
+
def other_advice
|
30
|
+
<<-EOA
|
31
|
+
Plugins defined defaults for fields that don't appear in templates.
|
32
|
+
|
33
|
+
It's possible that a plugin defined a default but it's template was
|
34
|
+
overridden, so the fields disappeared. Diecut doesn't yet check for
|
35
|
+
that case. In those cases, you can ignore this warning.
|
36
|
+
|
37
|
+
The other possiblity is that the default path has a typo. This is
|
38
|
+
especially likely if there's also a report about a missing output
|
39
|
+
field.
|
40
|
+
EOA
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/diecut/report.rb
CHANGED
@@ -15,7 +15,7 @@ module Diecut
|
|
15
15
|
|
16
16
|
def template
|
17
17
|
(<<-EOT).gsub(/^ /, '')
|
18
|
-
{{#reports}}{{#status_color}}{{name}}
|
18
|
+
{{#reports}}{{#status_color}}{{name}} {{status}} {{#length}} {{length}}{{/length}}
|
19
19
|
{{/status_color}}
|
20
20
|
{{#summary}}{{summary}}
|
21
21
|
{{/summary}}{{^empty }}{{#headers}}{{it}} {{/headers}}
|
@@ -24,6 +24,7 @@ module Diecut
|
|
24
24
|
{{advice}}
|
25
25
|
{{/advice}}
|
26
26
|
{{/reports}}
|
27
|
+
|
27
28
|
{{#status_color}}Total QA report items: {{total_items}}
|
28
29
|
Total QA failing reports: {{total_fails}}
|
29
30
|
{{/status_color}}
|
@@ -45,6 +46,14 @@ module Diecut
|
|
45
46
|
reports.inject(0){|sum, report| sum + (report.passed ? 0 : 1)}
|
46
47
|
end
|
47
48
|
|
49
|
+
def report_name_width
|
50
|
+
@report_name_width ||= reports.map(&:name).map(&:size).max
|
51
|
+
end
|
52
|
+
|
53
|
+
def sized_name(name)
|
54
|
+
array.take(widths.length).zip(widths).map{|item, width| { it: item.to_s.ljust(width)}}
|
55
|
+
end
|
56
|
+
|
48
57
|
def context(renderer)
|
49
58
|
bad_color = proc{|text,render| Paint[renderer.render(text), :red]}
|
50
59
|
good_color = proc{|text,render| Paint[renderer.render(text), :green]}
|
@@ -58,6 +67,7 @@ module Diecut
|
|
58
67
|
status_color: passed? ? good_color : bad_color
|
59
68
|
}
|
60
69
|
context[:reports].each do |report|
|
70
|
+
report[:name] = report[:name].rjust(report_name_width)
|
61
71
|
report[:status_color] =
|
62
72
|
case report[:status]
|
63
73
|
when /ok/i
|
data/lib/diecut.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'diecut/mediator'
|
2
2
|
require 'diecut/plugin-description'
|
3
3
|
require 'diecut/plugin-loader'
|
4
|
+
require 'diecut/errors'
|
4
5
|
|
5
6
|
module Diecut
|
6
7
|
class << self
|
@@ -24,6 +25,11 @@ module Diecut
|
|
24
25
|
plugin_loader.plugins
|
25
26
|
end
|
26
27
|
|
28
|
+
def issue_handler
|
29
|
+
@issue_handler ||= ErrorHandling::AllWarn.new
|
30
|
+
end
|
31
|
+
attr_writer :issue_handler
|
32
|
+
|
27
33
|
# Used in a `diecut_plugin.rb` file (either in the `lib/` of a gem, or at
|
28
34
|
# the local `~/.config/diecut/diecut_plugin.rb` to register a new plugin.
|
29
35
|
#
|
data/spec/linter_spec.rb
CHANGED
@@ -83,7 +83,7 @@ describe Diecut::Mill do
|
|
83
83
|
end
|
84
84
|
|
85
85
|
it "should produce a report" do
|
86
|
-
expect(report).to match(/Option collisions
|
86
|
+
expect(report).to match(/Option collisions\s*FAIL/)
|
87
87
|
expect(report).to match(/Total QA failing reports:/)
|
88
88
|
expect(report).to match(/there's/)
|
89
89
|
end
|
@@ -96,7 +96,7 @@ describe Diecut::Mill do
|
|
96
96
|
end
|
97
97
|
|
98
98
|
it "should produce a report" do
|
99
|
-
expect(report).to match(/Template fields all have settings
|
99
|
+
expect(report).to match(/Template fields all have settings\s*WARN/)
|
100
100
|
expect(report).to match(/Output field\s+Source file/)
|
101
101
|
expect(report).to match(/thing\s+{{testing}}.txt/)
|
102
102
|
expect(report).not_to match(/^\s*testing\b/)
|
@@ -112,7 +112,7 @@ describe Diecut::Mill do
|
|
112
112
|
end
|
113
113
|
|
114
114
|
it "should produce a report" do
|
115
|
-
expect(report).to match(/Overridden context defaults
|
115
|
+
expect(report).to match(/Overridden context defaults\s*OK/)
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
@@ -123,7 +123,7 @@ describe Diecut::Mill do
|
|
123
123
|
end
|
124
124
|
|
125
125
|
it "should produce a report" do
|
126
|
-
expect(report).to match(/Overridden context defaults
|
126
|
+
expect(report).to match(/Overridden context defaults\s*FAIL/)
|
127
127
|
expect(report).to match(/Output field\s+Default value\s+Source plugin/)
|
128
128
|
expect(report).to match(/thing\s+15\s+dummy/)
|
129
129
|
expect(report).to match(/Total QA failing reports:/)
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: diecut
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Judson Lester
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-02-
|
11
|
+
date: 2016-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mustache
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
@@ -83,7 +83,8 @@ dependencies:
|
|
83
83
|
description: ''
|
84
84
|
email:
|
85
85
|
- nyarly@gmail.com
|
86
|
-
executables:
|
86
|
+
executables:
|
87
|
+
- diecut
|
87
88
|
extensions: []
|
88
89
|
extra_rdoc_files: []
|
89
90
|
files:
|
@@ -94,6 +95,7 @@ files:
|
|
94
95
|
- lib/diecut/cli.rb
|
95
96
|
- lib/diecut/configurable.rb
|
96
97
|
- lib/diecut/context-handler.rb
|
98
|
+
- lib/diecut/error-report.rb
|
97
99
|
- lib/diecut/errors.rb
|
98
100
|
- lib/diecut/linter.rb
|
99
101
|
- lib/diecut/mediator.rb
|
@@ -103,6 +105,15 @@ files:
|
|
103
105
|
- lib/diecut/plugin-description/context-default.rb
|
104
106
|
- lib/diecut/plugin-description/option.rb
|
105
107
|
- lib/diecut/plugin-loader.rb
|
108
|
+
- lib/diecut/report-builder.rb
|
109
|
+
- lib/diecut/report-builders/exception-report.rb
|
110
|
+
- lib/diecut/report-builders/invalid-plugin.rb
|
111
|
+
- lib/diecut/report-builders/missing-context-field.rb
|
112
|
+
- lib/diecut/report-builders/option-collision.rb
|
113
|
+
- lib/diecut/report-builders/orphaned-field.rb
|
114
|
+
- lib/diecut/report-builders/overridden-context-defaults.rb
|
115
|
+
- lib/diecut/report-builders/template-list.rb
|
116
|
+
- lib/diecut/report-builders/unused-default.rb
|
106
117
|
- lib/diecut/report.rb
|
107
118
|
- lib/diecut/template-reducer.rb
|
108
119
|
- lib/diecut/template-set.rb
|
@@ -129,7 +140,7 @@ rdoc_options:
|
|
129
140
|
- "--main"
|
130
141
|
- doc/README
|
131
142
|
- "--title"
|
132
|
-
- diecut-0.0.
|
143
|
+
- diecut-0.0.3 Documentation
|
133
144
|
require_paths:
|
134
145
|
- lib/
|
135
146
|
required_ruby_version: !ruby/object:Gem::Requirement
|