def findbugs()

in contrib/findbugs/src/python/pants/contrib/findbugs/tasks/findbugs.py [0:0]


  def findbugs(self, target):
    runtime_classpaths = self.context.products.get_data('runtime_classpath')
    runtime_classpath = runtime_classpaths.get_for_targets(target.closure(bfs=True))
    aux_classpath = OrderedSet(jar for conf, jar in runtime_classpath if conf == 'default')

    target_jars = OrderedSet(jar for conf, jar in runtime_classpaths.get_for_target(target) if conf == 'default')

    bug_counts = { 'error': 0, 'high': 0, 'normal': 0, 'low': 0 }

    if not target_jars:
      self.context.log.info('  No jars to be analyzed')
      return bug_counts

    output_dir = os.path.join(self.workdir, target.id)
    safe_mkdir(output_dir)
    output_file = os.path.join(output_dir, 'findbugsXml.xml')

    aux_classpath_file = os.path.join(self.workdir, '{}.classpath'.format(os.path.basename(output_dir)))
    with open(aux_classpath_file, 'w') as f:
      f.write('\n'.join(aux_classpath - target_jars))

    args = [
      '-auxclasspathFromFile', aux_classpath_file,
      '-projectName', target.address.spec,
      '-xml:withMessages',
      '-effort:{}'.format(self.get_options().effort),
      '-{}'.format(self.get_options().threshold),
      '-nested:{}'.format('true' if self.get_options().nested else 'false'),
      '-output', output_file,
      '-noClassOk'
    ]

    if self.get_options().exclude_filter_file:
      args.extend(['-exclude', os.path.join(get_buildroot(), self.get_options().exclude_filter_file)])

    if self.get_options().include_filter_file:
      args.extend(['-include', os.path.join(get_buildroot(), self.get_options().include_filter_file)])

    if self.get_options().max_rank:
      args.extend(['-maxRank', str(self.get_options().max_rank)])

    if self.get_options().relaxed:
      args.extend(['-relaxed'])

    if self.get_options().level == 'debug':
      args.extend(['-progress'])

    args.extend(target_jars)

    # Try to run spotbugs with the same java version as the target
    # The minimum JDK for spotbugs is JDK 1.8
    min_jdk_version = max(target.platform.target_level, Revision.lenient('1.8'))
    if min_jdk_version.components[0] == 1:
      max_jdk_version = Revision(min_jdk_version.components[0], min_jdk_version.components[1], '9999')
    else:
      max_jdk_version = Revision(min_jdk_version.components[0], '9999')

    self.set_distribution(minimum_version=min_jdk_version, maximum_version=max_jdk_version, jdk=True)

    result = self.runjava(classpath=self.tool_classpath('findbugs'),
                          main=self._FINDBUGS_MAIN,
                          jvm_options=self.get_options().jvm_options,
                          args=args,
                          workunit_name='findbugs',
                          workunit_labels=[WorkUnitLabel.LINT])
    if result != 0:
      raise TaskError('java {main} ... exited non-zero ({result})'.format(
          main=self._FINDBUGS_MAIN, result=result))

    xml = XmlParser.from_file(output_file)
    for error in xml.parsed.getElementsByTagName('Error'):
      self.context.log.warn('Error: {msg}'.format(
        msg=error.getElementsByTagName('ErrorMessage')[0].firstChild.data))
      bug_counts['error'] += 1

    for bug_instance in xml.parsed.getElementsByTagName('BugInstance'):
      bug_rank = bug_instance.getAttribute('rank')
      if int(bug_rank) <= self._HIGH_PRIORITY_LOWEST_RANK:
        priority = 'high'
      elif int(bug_rank) <= self._NORMAL_PRIORITY_LOWEST_RANK:
        priority = 'normal'
      else:
        priority = 'low'
      bug_counts[priority] += 1

      source_line = bug_instance.getElementsByTagName('Class')[0].getElementsByTagName('SourceLine')[0]
      self.context.log.warn('Bug[{priority}]: {type} {desc} {line}'.format(
        priority=priority,
        type=bug_instance.getAttribute('type'),
        desc=bug_instance.getElementsByTagName('LongMessage')[0].firstChild.data,
        line=source_line.getElementsByTagName('Message')[0].firstChild.data))

    return bug_counts