Package org.sonar.batch.issue

Source Code of org.sonar.batch.issue.ModuleIssues

/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
package org.sonar.batch.issue;

import com.google.common.base.Objects;
import com.google.common.base.Strings;
import org.sonar.api.batch.debt.DebtRemediationFunction;
import org.sonar.api.batch.rule.ActiveRule;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.batch.rule.Rule;
import org.sonar.api.batch.rule.Rules;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.resources.Project;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.Violation;
import org.sonar.api.utils.Duration;
import org.sonar.api.utils.MessageException;
import org.sonar.core.issue.DefaultIssueBuilder;

import javax.annotation.Nullable;

/**
* Initialize the issues raised during scan.
*/
public class ModuleIssues {

  private final ActiveRules activeRules;
  private final Rules rules;
  private final IssueCache cache;
  private final Project project;
  private final IssueFilters filters;

  public ModuleIssues(ActiveRules activeRules, Rules rules, IssueCache cache, @Nullable Project project, IssueFilters filters) {
    this.activeRules = activeRules;
    this.rules = rules;
    this.cache = cache;
    this.project = project;
    this.filters = filters;
  }

  /**
   * Used by scan2
   */
  public ModuleIssues(ActiveRules activeRules, Rules rules, IssueCache cache, IssueFilters filters) {
    this(activeRules, rules, cache, null, filters);
  }

  public boolean initAndAddIssue(DefaultIssue issue) {
    return initAndAddIssue(issue, null);
  }

  public boolean initAndAddViolation(Violation violation) {
    DefaultIssue issue = newIssue(violation);
    return initAndAddIssue(issue, violation);
  }

  private DefaultIssue newIssue(Violation violation) {
    return (DefaultIssue) new DefaultIssueBuilder()
      .componentKey(violation.getResource().getEffectiveKey())
      // Project can be null but Violation not used by scan2
      .projectKey(project.getRoot().getEffectiveKey())
      .ruleKey(RuleKey.of(violation.getRule().getRepositoryKey(), violation.getRule().getKey()))
      .effortToFix(violation.getCost())
      .line(violation.getLineId())
      .message(violation.getMessage())
      .severity(violation.getSeverity() != null ? violation.getSeverity().name() : null)
      .build();
  }

  private boolean initAndAddIssue(DefaultIssue issue, @Nullable Violation violation) {
    RuleKey ruleKey = issue.ruleKey();
    Rule rule = rules.find(ruleKey);
    validateRule(issue, rule);
    ActiveRule activeRule = activeRules.find(ruleKey);
    if (activeRule == null) {
      // rule does not exist or is not enabled -> ignore the issue
      return false;
    }
    updateIssue(issue, rule, activeRule);
    if (filters.accept(issue, violation)) {
      cache.put(issue);
      return true;
    }
    return false;
  }

  private void validateRule(DefaultIssue issue, Rule rule) {
    RuleKey ruleKey = issue.ruleKey();
    if (rule == null) {
      throw MessageException.of(String.format("The rule '%s' does not exist.", ruleKey));
    }
    if (Strings.isNullOrEmpty(rule.name()) && Strings.isNullOrEmpty(issue.message())) {
      throw MessageException.of(String.format("The rule '%s' has no name and the related issue has no message.", ruleKey));
    }
  }

  private void updateIssue(DefaultIssue issue, Rule rule, ActiveRule activeRule) {
    if (Strings.isNullOrEmpty(issue.message())) {
      issue.setMessage(rule.name());
    }
    if (project != null) {
      issue.setCreationDate(project.getAnalysisDate());
      issue.setUpdateDate(project.getAnalysisDate());
    }
    if (issue.severity() == null) {
      issue.setSeverity(activeRule.severity());
    }
    DebtRemediationFunction function = rule.debtRemediationFunction();
    if (rule.debtSubCharacteristic() != null && function != null) {
      issue.setDebt(calculateDebt(function, issue.effortToFix(), rule.key()));
    }
  }

  private Duration calculateDebt(DebtRemediationFunction function, @Nullable Double effortToFix, RuleKey ruleKey) {
    if (DebtRemediationFunction.Type.CONSTANT_ISSUE.equals(function.type()) && effortToFix != null) {
      throw new IllegalArgumentException("Rule '" + ruleKey + "' can not use 'Constant/issue' remediation function " +
        "because this rule does not have a fixed remediation cost.");
    }
    Duration result = Duration.create(0);
    Duration factor = function.coefficient();
    Duration offset = function.offset();

    if (factor != null) {
      int effortToFixValue = Objects.firstNonNull(effortToFix, 1).intValue();
      result = factor.multiply(effortToFixValue);
    }
    if (offset != null) {
      result = result.add(offset);
    }
    return result;
  }

}
TOP

Related Classes of org.sonar.batch.issue.ModuleIssues

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.