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



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

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
216
# 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,
                                 env_name: 'FL_OCLINT_SELECT_REQEX',
                                 description: 'Select all files matching this reqex',
                                 skip_type_validation: true, # allows Regex
                                 deprecated: "Use `:select_regex` instead",
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :select_regex,
                                 env_name: 'FL_OCLINT_SELECT_REGEX',
                                 description: 'Select all files matching this regex',
                                 skip_type_validation: true, # allows Regex
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :exclude_regex,
                                 env_name: 'FL_OCLINT_EXCLUDE_REGEX',
                                 description: 'Exclude all files matching this regex',
                                 skip_type_validation: true, # allows Regex
                                 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",
                                 type: Boolean,
                                 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',
                                 type: Array,
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :enable_rules,
                                 env_name: 'FL_OCLINT_ENABLE_RULES',
                                 description: 'List of rules to pick explicitly',
                                 type: Array,
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :disable_rules,
                                 env_name: 'FL_OCLINT_DISABLE_RULES',
                                 description: 'List of rules to disable',
                                 type: Array,
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :max_priority_1,
                                 env_names: ["FL_OCLINT_MAX_PRIOTITY_1", "FL_OCLINT_MAX_PRIORITY_1"], # The version with typo must be deprecated
                                 description: 'The max allowed number of priority 1 violations',
                                 type: Integer,
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :max_priority_2,
                                 env_names: ["FL_OCLINT_MAX_PRIOTITY_2", "FL_OCLINT_MAX_PRIORITY_2"], # The version with typo must be deprecated
                                 description: 'The max allowed number of priority 2 violations',
                                 type: Integer,
                                 optional: true),
    FastlaneCore::ConfigItem.new(key: :max_priority_3,
                                 env_names: ["FL_OCLINT_MAX_PRIOTITY_3", "FL_OCLINT_MAX_PRIORITY_3"], # The version with typo must be deprecated
                                 description: 'The max allowed number of priority 3 violations',
                                 type: Integer,
                                 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",
                                 type: Boolean,
                                 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)",
                                 type: Boolean,
                                 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",
                                 type: Boolean,
                                 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



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

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



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

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



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
263
# File 'fastlane/lib/fastlane/actions/oclint.rb', line 237

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:



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

def self.is_supported?(platform)
  true
end

.outputObject

rubocop:enable Metrics/PerceivedComplexity



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

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