Class: Fastlane::Actions::OclintAction

Inherits:
Fastlane::Action show all
Defined in:
fastlane/lib/fastlane/actions/oclint.rb

Constant Summary

Constants inherited from Fastlane::Action

Fastlane::Action::AVAILABLE_CATEGORIES, Fastlane::Action::RETURN_TYPES

Documentation collapse

Class Method Summary collapse

Methods inherited from Fastlane::Action

action_name, authors, deprecated_notes, lane_context, method_missing, other_action, return_type, return_value, sample_return_value, shell_out_should_use_bundle_exec?, step_text

Class Method Details

.authorObject



224
225
226
# File 'fastlane/lib/fastlane/actions/oclint.rb', line 224

def self.author
  'HeEAaD'
end

.available_optionsObject



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'fastlane/lib/fastlane/actions/oclint.rb', line 120

def self.available_options
  [
    FastlaneCore::ConfigItem.new(key: :oclint_path,
                                 env_name: 'FL_OCLINT_PATH',
                                 description: 'The path to oclint binary',
                                 default_value: 'oclint',
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :compile_commands,
                                 env_name: 'FL_OCLINT_COMPILE_COMMANDS',
                                 description: 'The json compilation database, use xctool reporter \'json-compilation-database\'',
                                 default_value: 'compile_commands.json',
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :select_reqex, # select_reqex is deprecated, remove as soon as possible
                                 env_name: 'FL_OCLINT_SELECT_REQEX',
                                 description: 'Select all files matching this reqex',
                                 is_string: false,
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :select_regex,
                                 env_name: 'FL_OCLINT_SELECT_REGEX',
                                 description: 'Select all files matching this regex',
                                 is_string: false,
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :exclude_regex,
                                 env_name: 'FL_OCLINT_EXCLUDE_REGEX',
                                 description: 'Exclude all files matching this regex',
                                 is_string: false,
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :report_type,
                                 env_name: 'FL_OCLINT_REPORT_TYPE',
                                 description: 'The type of the report (default: html)',
                                 default_value: 'html',
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :report_path,
                                 env_name: 'FL_OCLINT_REPORT_PATH',
                                 description: 'The reports file path',
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :list_enabled_rules,
                                 env_name: "FL_OCLINT_LIST_ENABLED_RULES",
                                 description: "List enabled rules",
                                 is_string: false,
                                 default_value: false),
    FastlaneCore::ConfigItem.new(key: :rc,
                                 env_name: 'FL_OCLINT_RC',
                                 description: 'Override the default behavior of rules',
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :thresholds,
                                 env_name: 'FL_OCLINT_THRESHOLDS',
                                 description: 'List of rule thresholds to override the default behavior of rules',
                                 is_string: false,
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :enable_rules,
                                 env_name: 'FL_OCLINT_ENABLE_RULES',
                                 description: 'List of rules to pick explicitly',
                                 is_string: false,
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :disable_rules,
                                 env_name: 'FL_OCLINT_DISABLE_RULES',
                                 description: 'List of rules to disable',
                                 is_string: false,
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :max_priority_1,
                                 env_name: 'FL_OCLINT_MAX_PRIOTITY_1',
                                 description: 'The max allowed number of priority 1 violations',
                                 is_string: false,
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :max_priority_2,
                                 env_name: 'FL_OCLINT_MAX_PRIOTITY_2',
                                 description: 'The max allowed number of priority 2 violations',
                                 is_string: false,
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :max_priority_3,
                                 env_name: 'FL_OCLINT_MAX_PRIOTITY_3',
                                 description: 'The max allowed number of priority 3 violations',
                                 is_string: false,
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :enable_clang_static_analyzer,
                                 env_name: "FL_OCLINT_ENABLE_CLANG_STATIC_ANALYZER",
                                 description: "Enable Clang Static Analyzer, and integrate results into OCLint report",
                                 is_string: false,
                                 default_value: false),
    FastlaneCore::ConfigItem.new(key: :enable_global_analysis,
                                 env_name: "FL_OCLINT_ENABLE_GLOBAL_ANALYSIS",
                                 description: "Compile every source, and analyze across global contexts (depends on number of source files, could results in high memory load)",
                                 is_string: false,
                                 default_value: false),
    FastlaneCore::ConfigItem.new(key: :allow_duplicated_violations,
                                 env_name: "FL_OCLINT_ALLOW_DUPLICATED_VIOLATIONS",
                                 description: "Allow duplicated violations in the OCLint report",
                                 is_string: false,
                                 default_value: false),
    FastlaneCore::ConfigItem.new(key: :extra_arg,
                                 env_name: 'FL_OCLINT_EXTRA_ARG',
                                 description: 'Additional argument to append to the compiler command line',
                                 optional: true)
  ]
end

.categoryObject



264
265
266
# File 'fastlane/lib/fastlane/actions/oclint.rb', line 264

def self.category
  :testing
end

.descriptionObject



116
117
118
# File 'fastlane/lib/fastlane/actions/oclint.rb', line 116

def self.description
  "Lints implementation files with OCLint"
end

.detailsObject



232
233
234
# File 'fastlane/lib/fastlane/actions/oclint.rb', line 232

def self.details
  "Run the static analyzer tool [OCLint](http://oclint.org) for your project. You need to have a `compile_commands.json` file in your _fastlane_ directory or pass a path to your file."
end

.ensure_array_is_not_string!(array) ⇒ Object

return a proper array of strings if array string is single-quoted



106
107
108
109
110
# File 'fastlane/lib/fastlane/actions/oclint.rb', line 106

def self.ensure_array_is_not_string!(array)
  return array unless array.kind_of?(String)

  array.split(',')
end

.ensure_regex_is_not_string!(regex) ⇒ Object

return a proper regex object if regex string is single-quoted



99
100
101
102
103
# File 'fastlane/lib/fastlane/actions/oclint.rb', line 99

def self.ensure_regex_is_not_string!(regex)
  return regex unless regex.kind_of?(String)

  Regexp.new(regex)
end

.example_codeObject



236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'fastlane/lib/fastlane/actions/oclint.rb', line 236

def self.example_code
  [
    'oclint(
      compile_commands: "commands.json",    # The JSON compilation database, use xctool reporter "json-compilation-database"
      select_regex: /ViewController.m/,     # Select all files matching this regex
      exclude_regex: /Test.m/,              # Exclude all files matching this regex
      report_type: "pmd",                   # The type of the report (default: html)
      max_priority_1: 10,                   # The max allowed number of priority 1 violations
      max_priority_2: 100,                  # The max allowed number of priority 2 violations
      max_priority_3: 1000,                 # The max allowed number of priority 3 violations
      thresholds: [                         # Override the default behavior of rules
        "LONG_LINE=200",
        "LONG_METHOD=200"
      ],
      enable_rules: [                       # List of rules to pick explicitly
        "DoubleNegative",
        "SwitchStatementsDon\'TNeedDefaultWhenFullyCovered"
      ],
      disable_rules: ["GotoStatement"],     # List of rules to disable
      list_enabled_rules: true,             # List enabled rules
      enable_clang_static_analyzer: true,   # Enable Clang Static Analyzer, and integrate results into OCLint report
      enable_global_analysis: true,         # Compile every source, and analyze across global contexts (depends on number of source files, could results in high memory load)
      allow_duplicated_violations: true,    # Allow duplicated violations in the OCLint report
      extra_arg: "-Wno-everything"          # Additional argument to append to the compiler command line
    )'
  ]
end

.is_supported?(platform) ⇒ Boolean

Returns:



228
229
230
# File 'fastlane/lib/fastlane/actions/oclint.rb', line 228

def self.is_supported?(platform)
  true
end

.outputObject

rubocop:enable Metrics/PerceivedComplexity



218
219
220
221
222
# File 'fastlane/lib/fastlane/actions/oclint.rb', line 218

def self.output
  [
    ['FL_OCLINT_REPORT_PATH', 'The reports file path']
  ]
end

.run(params) ⇒ Object

rubocop:disable Metrics/PerceivedComplexity



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'fastlane/lib/fastlane/actions/oclint.rb', line 9

def self.run(params)
  oclint_path = params[:oclint_path]
  if `which #{oclint_path}`.to_s.empty? && !Helper.test?
    UI.user_error!("You have to install oclint or provide path to oclint binary. Fore more details: ") + "http://docs.oclint.org/en/stable/intro/installation.html".yellow
  end

  compile_commands = params[:compile_commands]
  compile_commands_dir = params[:compile_commands]
  UI.user_error!("Could not find json compilation database at path '#{compile_commands}'") unless File.exist?(compile_commands)

  # We'll attempt to sort things out so that we support receiving either a path to a
  # 'compile_commands.json' file (as our option asks for), or a path to a directory
  # *containing* a 'compile_commands.json' file (as oclint actually wants)
  if File.file?(compile_commands_dir)
    compile_commands_dir = File.dirname(compile_commands_dir)
  else
    compile_commands = File.join(compile_commands_dir, 'compile_commands.json')
  end

  if params[:select_reqex]
    UI.important("'select_reqex' parameter is deprecated. Please use 'select_regex' instead.")
    select_regex = params[:select_reqex]
  end

  select_regex = params[:select_regex] if params[:select_regex] # Overwrite deprecated select_reqex
  select_regex = ensure_regex_is_not_string!(select_regex)

  exclude_regex = params[:exclude_regex]
  exclude_regex = ensure_regex_is_not_string!(exclude_regex)

  files = JSON.parse(File.read(compile_commands)).map do |compile_command|
    file = compile_command['file']
    File.exist?(file) ? file : File.join(compile_command['directory'], file)
  end

  files.uniq!
  files.select! do |file|
    file_ruby = file.gsub('\ ', ' ')
    File.exist?(file_ruby) and
      (!select_regex or file_ruby =~ select_regex) and
      (!exclude_regex or file_ruby !~ exclude_regex)
  end

  command_prefix = [
    'cd',
    File.expand_path('.').shellescape,
    '&&'
  ].join(' ')

  report_type = params[:report_type]
  report_path = params[:report_path] ? params[:report_path] : 'oclint_report.' + report_type

  oclint_args = ["-report-type=#{report_type}", "-o=#{report_path}"]

  oclint_args << "-list-enabled-rules" if params[:list_enabled_rules]

  if params[:rc]
    UI.important("It's recommended to use 'thresholds' instead of deprecated 'rc' parameter")
    oclint_args << "-rc=#{params[:rc]}" if params[:rc] # Deprecated
  end

  oclint_args << ensure_array_is_not_string!(params[:thresholds]).map { |t| "-rc=#{t}" } if params[:thresholds]
  # Escape ' in rule names with \' when passing on to shell command
  oclint_args << params[:enable_rules].map { |r| "-rule #{r.shellescape}" } if params[:enable_rules]
  oclint_args << params[:disable_rules].map { |r| "-disable-rule #{r.shellescape}" } if params[:disable_rules]

  oclint_args << "-max-priority-1=#{params[:max_priority_1]}" if params[:max_priority_1]
  oclint_args << "-max-priority-2=#{params[:max_priority_2]}" if params[:max_priority_2]
  oclint_args << "-max-priority-3=#{params[:max_priority_3]}" if params[:max_priority_3]

  oclint_args << "-enable-clang-static-analyzer" if params[:enable_clang_static_analyzer]
  oclint_args << "-enable-global-analysis" if params[:enable_global_analysis]
  oclint_args << "-allow-duplicated-violations" if params[:allow_duplicated_violations]
  oclint_args << "-p #{compile_commands_dir.shellescape}"

  oclint_args << "-extra-arg=#{params[:extra_arg]}" if params[:extra_arg]

  command = [
    command_prefix,
    oclint_path,
    oclint_args,
    '"' + files.join('" "') + '"'
  ].join(' ')

  Actions.lane_context[SharedValues::FL_OCLINT_REPORT_PATH] = File.expand_path(report_path)

  return Action.sh(command)
end