diecut 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|