lint_trappings 0.1.0
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 +7 -0
- data/LICENSE.md +21 -0
- data/lib/lint_trappings.rb +17 -0
- data/lib/lint_trappings/application.rb +138 -0
- data/lib/lint_trappings/arguments_parser.rb +145 -0
- data/lib/lint_trappings/cli.rb +61 -0
- data/lib/lint_trappings/command/base.rb +36 -0
- data/lib/lint_trappings/command/display_documentation.rb +65 -0
- data/lib/lint_trappings/command/display_formatters.rb +14 -0
- data/lib/lint_trappings/command/display_help.rb +8 -0
- data/lib/lint_trappings/command/display_linters.rb +24 -0
- data/lib/lint_trappings/command/display_version.rb +14 -0
- data/lib/lint_trappings/command/scan.rb +19 -0
- data/lib/lint_trappings/configuration.rb +94 -0
- data/lib/lint_trappings/configuration_loader.rb +98 -0
- data/lib/lint_trappings/configuration_resolver.rb +49 -0
- data/lib/lint_trappings/document.rb +45 -0
- data/lib/lint_trappings/errors.rb +127 -0
- data/lib/lint_trappings/executable.rb +26 -0
- data/lib/lint_trappings/file_finder.rb +171 -0
- data/lib/lint_trappings/formatter/base.rb +67 -0
- data/lib/lint_trappings/formatter/checkstyle.rb +34 -0
- data/lib/lint_trappings/formatter/default.rb +99 -0
- data/lib/lint_trappings/formatter/json.rb +62 -0
- data/lib/lint_trappings/formatter_forwarder.rb +23 -0
- data/lib/lint_trappings/formatter_loader.rb +45 -0
- data/lib/lint_trappings/lint.rb +37 -0
- data/lib/lint_trappings/linter.rb +182 -0
- data/lib/lint_trappings/linter_configuration_validator.rb +42 -0
- data/lib/lint_trappings/linter_loader.rb +44 -0
- data/lib/lint_trappings/linter_plugin.rb +35 -0
- data/lib/lint_trappings/linter_selector.rb +120 -0
- data/lib/lint_trappings/location.rb +39 -0
- data/lib/lint_trappings/output.rb +118 -0
- data/lib/lint_trappings/preprocessor.rb +41 -0
- data/lib/lint_trappings/rake_task.rb +145 -0
- data/lib/lint_trappings/report.rb +58 -0
- data/lib/lint_trappings/runner.rb +161 -0
- data/lib/lint_trappings/spec.rb +12 -0
- data/lib/lint_trappings/spec/directory_helpers.rb +22 -0
- data/lib/lint_trappings/spec/indentation_helpers.rb +7 -0
- data/lib/lint_trappings/spec/matchers/report_lint_matcher.rb +169 -0
- data/lib/lint_trappings/spec/shared_contexts/linter_shared_context.rb +35 -0
- data/lib/lint_trappings/utils.rb +123 -0
- data/lib/lint_trappings/version.rb +4 -0
- metadata +117 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e033fd62166d774b4a18cc1c1a05713f194c22b7
|
4
|
+
data.tar.gz: 95160b22578c977eb2ed213c1ffd9ed665b5f4cd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5d917e31b883e44ca39cf96f02190242a321801bb1d72ca72643018930f07e83d27bbc60193a88d92c166cc257b94a33af381fe1b39a488066fef7c115627f22
|
7
|
+
data.tar.gz: b6134bc6b4559a063ba496fae837517e5c8f36fa46ea7f2a2f07a85944f5376151136291e909fa6cc95fe715b43264e7179dc77f97c01607bbb88202ea7c879e
|
data/LICENSE.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
LintTrappings is released under the MIT license.
|
2
|
+
|
3
|
+
> Copyright (c) 2016 Shane da Silva. http://shane.io
|
4
|
+
>
|
5
|
+
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
> of this software and associated documentation files (the "Software"), to deal
|
7
|
+
> in the Software without restriction, including without limitation the rights
|
8
|
+
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
> copies of the Software, and to permit persons to whom the Software is
|
10
|
+
> furnished to do so, subject to the following conditions:
|
11
|
+
>
|
12
|
+
> The above copyright notice and this permission notice shall be included in
|
13
|
+
> all copies or substantial portions of the Software.
|
14
|
+
>
|
15
|
+
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
> SOFTWARE.
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Load all modules necessary to work with the framework.
|
2
|
+
# Ordering here can be important depending on class references in each module.
|
3
|
+
|
4
|
+
require 'lint_trappings/errors'
|
5
|
+
require 'lint_trappings/configuration'
|
6
|
+
require 'lint_trappings/utils'
|
7
|
+
require 'lint_trappings/file_finder'
|
8
|
+
require 'lint_trappings/output'
|
9
|
+
require 'lint_trappings/document'
|
10
|
+
require 'lint_trappings/location'
|
11
|
+
require 'lint_trappings/lint'
|
12
|
+
require 'lint_trappings/linter'
|
13
|
+
require 'lint_trappings/linter_loader'
|
14
|
+
require 'lint_trappings/linter_selector'
|
15
|
+
require 'lint_trappings/report'
|
16
|
+
require 'lint_trappings/runner'
|
17
|
+
require 'lint_trappings/application'
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'lint_trappings/errors'
|
2
|
+
require 'lint_trappings/configuration_loader'
|
3
|
+
require 'lint_trappings/configuration_resolver'
|
4
|
+
|
5
|
+
module LintTrappings
|
6
|
+
# Linter application superclass.
|
7
|
+
#
|
8
|
+
# Implementors will subclass this and specify a number of high-level
|
9
|
+
# configuration options which will help the class run your custom application.
|
10
|
+
#
|
11
|
+
# @abstract
|
12
|
+
class Application
|
13
|
+
# Define an application configuration attribute.
|
14
|
+
#
|
15
|
+
# This is intended to be used to make specifying the configuration for a
|
16
|
+
# LintTrappings application easy. It defines a class instance variable which is
|
17
|
+
# specified in the body of the class itself via DSL-like method call, and
|
18
|
+
# also defines a method so the value can be obtained from a single instance.
|
19
|
+
def self.class_attribute(attr_name)
|
20
|
+
# Define DSL getter/setter
|
21
|
+
metaclass = (class << self; self; end)
|
22
|
+
metaclass.instance_eval do
|
23
|
+
define_method(attr_name) do |*args|
|
24
|
+
if args.any?
|
25
|
+
instance_variable_set(:"@#{attr_name}", args.first)
|
26
|
+
else
|
27
|
+
value = instance_variable_get(:"@#{attr_name}")
|
28
|
+
|
29
|
+
if value.nil?
|
30
|
+
raise ApplicationConfigurationError,
|
31
|
+
"`#{attr_name}` class attribute must be defined in #{self}!"
|
32
|
+
end
|
33
|
+
|
34
|
+
value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Define method on the class
|
40
|
+
define_method(attr_name) do
|
41
|
+
self.class.send(attr_name)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# @return [String] Proper name of this application
|
46
|
+
class_attribute :name
|
47
|
+
|
48
|
+
# @return [String] Name of the application executable
|
49
|
+
class_attribute :executable_name
|
50
|
+
|
51
|
+
# @return [String] Application version
|
52
|
+
class_attribute :version
|
53
|
+
|
54
|
+
# @return [LintTrappings::Configuration] Base configuration which all other
|
55
|
+
# configurations extend (can be empty if desired). This should be the same
|
56
|
+
# class as the configuration_class attribute.
|
57
|
+
class_attribute :base_configuration
|
58
|
+
|
59
|
+
# @return [String] Configuration file names to look for, in order of
|
60
|
+
# precedence (first one found wins)
|
61
|
+
class_attribute :configuration_file_names
|
62
|
+
|
63
|
+
# @return [String] List of file extensions the application can lint
|
64
|
+
class_attribute :file_extensions
|
65
|
+
|
66
|
+
# @return [String] URL of the application's home page
|
67
|
+
class_attribute :home_url
|
68
|
+
|
69
|
+
# @return [String] URL of the application's issue and bug reports page
|
70
|
+
class_attribute :issues_url
|
71
|
+
|
72
|
+
# @return [String] Directory prefix where gem stores built-in linters
|
73
|
+
class_attribute :linters_directory
|
74
|
+
|
75
|
+
# @return [Class] Base class of all linters for this application
|
76
|
+
class_attribute :linter_base_class
|
77
|
+
|
78
|
+
# @return [Class] Class to use when loading/parsing documents
|
79
|
+
class_attribute :document_class
|
80
|
+
|
81
|
+
# @param output [LintTrappings::Output]
|
82
|
+
def initialize(output)
|
83
|
+
@output = output
|
84
|
+
end
|
85
|
+
|
86
|
+
def run(options = {})
|
87
|
+
@output.color_enabled = options.fetch(:color, @output.tty?)
|
88
|
+
config = load_configuration(options)
|
89
|
+
|
90
|
+
command = create_command(options[:command]).new(self, config, options, @output)
|
91
|
+
command.run
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def create_command(command)
|
97
|
+
raise InvalidCommandError,
|
98
|
+
'`command` option must be specified!' unless command
|
99
|
+
|
100
|
+
command = command.to_s
|
101
|
+
|
102
|
+
require 'lint_trappings/command/base'
|
103
|
+
begin
|
104
|
+
require "lint_trappings/command/#{Utils.snake_case(command)}"
|
105
|
+
rescue LoadError, SyntaxError => ex
|
106
|
+
raise InvalidCommandError,
|
107
|
+
"Unable to load command '#{command}': #{ex.message}"
|
108
|
+
end
|
109
|
+
|
110
|
+
Command.const_get(Utils.camel_case(command))
|
111
|
+
end
|
112
|
+
|
113
|
+
# Loads the application configuration.
|
114
|
+
#
|
115
|
+
# @param options [Hash]
|
116
|
+
#
|
117
|
+
# @return [LintTrappings::Configuration]
|
118
|
+
def load_configuration(options)
|
119
|
+
config_loader = ConfigurationLoader.new(self)
|
120
|
+
|
121
|
+
config =
|
122
|
+
if options[:config_file]
|
123
|
+
config_loader.load_file(options[:config_file])
|
124
|
+
else
|
125
|
+
begin
|
126
|
+
config_loader.load(working_directory: Dir.pwd)
|
127
|
+
rescue NoConfigurationFileError
|
128
|
+
base_configuration
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
config = ConfigurationResolver.new(config_loader).resolve(config, options)
|
133
|
+
|
134
|
+
# Always extend the base/default configuration
|
135
|
+
base_configuration.merge(config)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module LintTrappings
|
4
|
+
# Handles option parsing for the command line application.
|
5
|
+
class ArgumentsParser
|
6
|
+
def initialize(application)
|
7
|
+
@application = application
|
8
|
+
end
|
9
|
+
|
10
|
+
# Parses command line options into an options hash.
|
11
|
+
#
|
12
|
+
# @param args [Array<String>] arguments passed via the command line
|
13
|
+
#
|
14
|
+
# @return [Hash] parsed options
|
15
|
+
def parse(args)
|
16
|
+
@options = {}
|
17
|
+
@options[:command] = :scan # Default command is to scan for lints
|
18
|
+
|
19
|
+
OptionParser.new do |parser|
|
20
|
+
parser.banner = "Usage: #{@application.executable_name} [options] [file1, file2, ...]"
|
21
|
+
|
22
|
+
add_linter_options parser
|
23
|
+
add_file_options parser
|
24
|
+
add_misc_options parser
|
25
|
+
add_info_options parser
|
26
|
+
end.parse!(args)
|
27
|
+
|
28
|
+
# Any remaining arguments are assumed to be files that should be linted
|
29
|
+
@options[:included_paths] = args
|
30
|
+
|
31
|
+
@options
|
32
|
+
rescue OptionParser::InvalidOption => ex
|
33
|
+
raise InvalidCliOptionError,
|
34
|
+
"#{ex.message}\nRun `#{@application.executable_name} --help` to " \
|
35
|
+
'see a list of available options.'
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# Register file-related flags.
|
41
|
+
def add_file_options(parser)
|
42
|
+
parser.on('-c', '--config config-file', String,
|
43
|
+
'Specify which configuration file you want to use') do |conf_file|
|
44
|
+
@options[:config_file] = conf_file
|
45
|
+
end
|
46
|
+
|
47
|
+
parser.on('-e', '--exclude-path file', String,
|
48
|
+
'List of file paths to exclude') do |file_path|
|
49
|
+
(@options[:excluded_paths] ||= []) << file_path
|
50
|
+
end
|
51
|
+
|
52
|
+
parser.on('-f', '--format formatter-name', String,
|
53
|
+
'Specify which output format you want') do |formatter_name|
|
54
|
+
(@options[:formatters] ||= []) << {
|
55
|
+
formatter_name => :stdout,
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
parser.on('-o', '--out output-file-path', String,
|
60
|
+
'Specify a file to write output to') do |file_path|
|
61
|
+
if @options[:formatters]
|
62
|
+
# Change the last specified formatter to output to the given file
|
63
|
+
last_formatter = @options[:formatters].last
|
64
|
+
last_formatter[last_formatter.keys.first] = file_path
|
65
|
+
else
|
66
|
+
# Otherwise if no formatters have been specified yet, set the default
|
67
|
+
# formatter to write to the given file
|
68
|
+
@options[:formatters] << { 'Default' => file_path }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
parser.on('--stdin-file-path file-path', String,
|
73
|
+
'Specify the path name for the file passed via STDIN') do |file_path|
|
74
|
+
@options[:stdin] = STDIN
|
75
|
+
@options[:stdin_file_path] = file_path
|
76
|
+
end
|
77
|
+
|
78
|
+
parser.on('-r', '--require require-path', String,
|
79
|
+
'Specify a path to `require`') do |require_path|
|
80
|
+
(@options[:require_paths] ||= []) << require_path
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Register linter-related flags.
|
85
|
+
def add_linter_options(parser)
|
86
|
+
parser.on('-i', '--include-linter linter', String,
|
87
|
+
'Specify which linters you want to run ' \
|
88
|
+
'(overrides those in your configuration)') do |linter|
|
89
|
+
(@options[:included_linters] ||= []).concat(linter.split(/\s*,\s*/))
|
90
|
+
end
|
91
|
+
|
92
|
+
parser.on('-x', '--exclude-linter linter', String,
|
93
|
+
"Specify which linters you don't want to run " \
|
94
|
+
'(in addition to those disabled by your configuration)') do |linter|
|
95
|
+
(@options[:excluded_linters] ||= []).concat(linter.split(/\s*,\s*/))
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def add_misc_options(parser)
|
100
|
+
parser.on('-C', '--concurrency workers', Integer,
|
101
|
+
'Specify the number of concurrent workers you want') do |workers|
|
102
|
+
@options[:concurrency] = workers
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Register informational flags.
|
107
|
+
def add_info_options(parser)
|
108
|
+
parser.on('--show-linters',
|
109
|
+
'Display available linters and whether or not they are enabled') do
|
110
|
+
@options[:command] = :display_linters
|
111
|
+
end
|
112
|
+
|
113
|
+
parser.on('--show-formatters', 'Display available formatters') do
|
114
|
+
@options[:command] = :display_formatters
|
115
|
+
end
|
116
|
+
|
117
|
+
parser.on('--show-docs [linter-name]', '--show-documentation [linter-name]') do |linter_name|
|
118
|
+
@options[:command] = :display_documentation
|
119
|
+
@options[:linter] = linter_name
|
120
|
+
end
|
121
|
+
|
122
|
+
parser.on('--[no-]color', 'Force output to be colorized') do |color|
|
123
|
+
@options[:color] = color
|
124
|
+
end
|
125
|
+
|
126
|
+
parser.on('-d', '--debug', 'Enable debug mode for more verbose output') do
|
127
|
+
@options[:debug] = true
|
128
|
+
end
|
129
|
+
|
130
|
+
parser.on_tail('-h', '--help', 'Display help documentation') do
|
131
|
+
@options[:command] = :display_help
|
132
|
+
@options[:help_message] = parser.help
|
133
|
+
end
|
134
|
+
|
135
|
+
parser.on_tail('-v', '--version', 'Display version') do
|
136
|
+
@options[:command] = :display_version
|
137
|
+
end
|
138
|
+
|
139
|
+
parser.on_tail('-V', '--verbose-version', 'Display verbose version information') do
|
140
|
+
@options[:command] = :display_version
|
141
|
+
@options[:verbose_version] = true
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'lint_trappings'
|
2
|
+
require 'lint_trappings/arguments_parser'
|
3
|
+
|
4
|
+
module LintTrappings
|
5
|
+
# Command line application interface.
|
6
|
+
class Cli
|
7
|
+
# @param application [LintTrappings::Application]
|
8
|
+
# @param output [LintTrappings::Output] stderr stream
|
9
|
+
def initialize(application, output)
|
10
|
+
@application = application
|
11
|
+
@output = output
|
12
|
+
end
|
13
|
+
|
14
|
+
# Parses the given command line arguments and executes appropriate logic
|
15
|
+
# based on those arguments.
|
16
|
+
#
|
17
|
+
# @param args [Array<String>] command line arguments
|
18
|
+
#
|
19
|
+
# @return [Integer] exit status code
|
20
|
+
def run(args)
|
21
|
+
options = ArgumentsParser.new(@application).parse(args)
|
22
|
+
@application.run(options)
|
23
|
+
0 # OK
|
24
|
+
rescue ScanWarned, ScanFailed => ex
|
25
|
+
# Special errors which we don't want to display, but do want their exit status
|
26
|
+
ex.exit_status
|
27
|
+
rescue => ex
|
28
|
+
handle_exception(ex)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
# Returns an appropriate error code for the specified exception, and outputs
|
34
|
+
# a message if necessary.
|
35
|
+
def handle_exception(ex)
|
36
|
+
if ex.is_a?(LintTrappings::LintTrappingsError) && ex.exit_status != 70
|
37
|
+
@output.error ex.message
|
38
|
+
ex.exit_status
|
39
|
+
else
|
40
|
+
print_unexpected_exception(ex)
|
41
|
+
ex.respond_to?(:exit_status) ? ex.exit_status : 70
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Outputs the backtrace of an exception with instructions on how to report
|
46
|
+
# the issue.
|
47
|
+
def print_unexpected_exception(ex)
|
48
|
+
@output.bold_error ex.message
|
49
|
+
@output.error ex.backtrace.join("\n")
|
50
|
+
@output.warning 'Report this bug at ', false
|
51
|
+
@output.info @application.issues_url
|
52
|
+
@output.newline
|
53
|
+
@output.success 'To help fix this issue, please include:'
|
54
|
+
@output.puts '- The above stack trace'
|
55
|
+
@output.print "- #{@application.name} version: "
|
56
|
+
@output.info @application.version
|
57
|
+
@output.print '- Ruby version: '
|
58
|
+
@output.info RUBY_VERSION
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module LintTrappings::Command
|
2
|
+
# Abstract base class of all commands.
|
3
|
+
#
|
4
|
+
# @abstract
|
5
|
+
class Base
|
6
|
+
# @param application [LintTrappings::Application]
|
7
|
+
# @param config [LintTrappings::Configuration]
|
8
|
+
# @param options [Hash]
|
9
|
+
# @param output [LintTrappings::Output]
|
10
|
+
def initialize(application, config, options, output)
|
11
|
+
@application = application
|
12
|
+
@config = config
|
13
|
+
@options = options
|
14
|
+
@output = output
|
15
|
+
end
|
16
|
+
|
17
|
+
# Runs the command.
|
18
|
+
def run
|
19
|
+
raise NotImplementedError, 'Define `execute` in `Command::Base` subclass'
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
# @return [LintTrappings::Application]
|
25
|
+
attr_reader :application
|
26
|
+
|
27
|
+
# @return [LintTrappings::Configuration]
|
28
|
+
attr_reader :config
|
29
|
+
|
30
|
+
# @return [Hash]
|
31
|
+
attr_reader :options
|
32
|
+
|
33
|
+
# @return [LintTrappings::Output]
|
34
|
+
attr_reader :output
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'terminal-table'
|
2
|
+
|
3
|
+
module LintTrappings::Command
|
4
|
+
# Displays documentation for the specified linter
|
5
|
+
class DisplayDocumentation < Base
|
6
|
+
def run
|
7
|
+
LintTrappings::LinterLoader.new(application, config).load(options)
|
8
|
+
|
9
|
+
output.info 'Linter Documentation'
|
10
|
+
output.info '--------------------'
|
11
|
+
|
12
|
+
linter_classes(options).sort_by(&:canonical_name).each do |linter_class|
|
13
|
+
display_linter_doc(linter_class)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def display_linter_doc(linter_class)
|
20
|
+
output.newline
|
21
|
+
output.notice linter_class.canonical_name
|
22
|
+
output.puts linter_class.description
|
23
|
+
output.newline
|
24
|
+
|
25
|
+
return unless linter_class.options.any?
|
26
|
+
|
27
|
+
table = Terminal::Table.new do |t|
|
28
|
+
t << %w[Option Description Type Default]
|
29
|
+
|
30
|
+
t.add_separator
|
31
|
+
|
32
|
+
linter_class.options.each do |option_name, option_spec|
|
33
|
+
t << [
|
34
|
+
option_name,
|
35
|
+
option_spec[:description],
|
36
|
+
option_spec[:type],
|
37
|
+
display_value(option_spec[:default]),
|
38
|
+
]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
output.puts table.to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
def display_value(value)
|
46
|
+
if value.is_a?(Array)
|
47
|
+
value.map { |v| "- #{v}" }.join("\n")
|
48
|
+
else
|
49
|
+
value
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def linter_classes(options)
|
54
|
+
if options[:linter]
|
55
|
+
begin
|
56
|
+
[application.linter_base_class.const_get(options[:linter])]
|
57
|
+
rescue NameError
|
58
|
+
raise NoSuchLinter, "No linter named #{options[:linter]} exists!"
|
59
|
+
end
|
60
|
+
else
|
61
|
+
application.linter_base_class.descendants
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|