lint_trappings 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|