// SonarQube, open source software quality management tool.
// Copyright (C) 2008-2016 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.


// IMPORTANT
// This is beta version of specification. It will evolve during next
// releases and is not forward-compatible yet.

syntax = "proto3";

import "constants.proto";

option java_package = "org.sonar.scanner.protocol.output";
option optimize_for = SPEED;

message Metadata {
  int64 analysis_date = 1;
  reserved 2; // organization drop
  // TODO should we keep this project_key here or not ? Because it's a duplication of Component.key
  string project_key = 3;

  reserved 4; // deprecated_branch (legacy branches feature)

  int32 root_component_ref = 5;
  bool cross_project_duplication_activated = 6;
  map<string, QProfile> qprofiles_per_language = 7;
  map<string, Plugin> plugins_by_key = 8;

  string branch_name = 9;
  BranchType branch_type = 10;
  string reference_branch_name = 11;

  string relative_path_from_scm_root = 12;
  string scm_revision_id = 13;

  string pull_request_key = 14;

  reserved 15; // modules_project_relative_path_by_key (no longer used)

  string projectVersion = 16;
  string buildString = 17;

  string target_branch_name = 18;

  reserved 19; // forkDate (no longer used)

  map<string, int32> not_analyzed_files_by_language = 20;

  string new_code_reference_branch = 21;

  message QProfile {
    string key = 1;
    string name = 2;
    string language = 3;
    int64 rulesUpdatedAt = 4;
  }

  message Plugin {
    string key = 1;
    int64 updatedAt = 2;
  }

  enum BranchType {
    UNSET = 0;
    BRANCH = 1;
    PULL_REQUEST = 2;
  }
}

message ContextProperty {
  string key = 1;
  string value = 2;
}

message TelemetryEntry {
  string key = 1;
  string value = 2;
}

message ActiveRule {
  string rule_repository = 1;
  string rule_key = 2;
  Severity severity = 3;
  map<string, string> params_by_key = 4;
  int64 createdAt = 5;
  int64 updatedAt = 6;
  string q_profile_key = 7;
  repeated Impact impacts = 8;
}

message ComponentLink {
  ComponentLinkType type = 1;
  string href = 2;

  enum ComponentLinkType {
    UNSET = 0;
    HOME = 1;
    SCM = 2;
    // SCM_DEV is no more set since 7.1. See SONAR-10299
    IGNORED_SCM_DEV = 3;
    ISSUE = 4;
    CI = 5;
  }
}

message Component {
  int32 ref = 1;

  string name = 3;
  ComponentType type = 4;
  bool is_test = 5;
  string language = 6;
  repeated int32 child_ref = 7 [packed = true];
  repeated ComponentLink link = 8;
  // Only available on PROJECT and MODULE types
  // TODO rename this property -> moduleKey ?
  string key = 10;
  // Only available on FILE type, should always be at least 1
  int32 lines = 11;
  // Only available on PROJECT and MODULE types
  string description = 12;
  FileStatus status = 13;

  // Path relative to project base directory
  string project_relative_path = 14;
  bool markedAsUnchanged = 15;
  string old_relative_file_path = 16;

  enum ComponentType {
    UNSET = 0;
    PROJECT = 1;
    MODULE = 2 [deprecated = true];
    DIRECTORY = 3 [deprecated = true];
    FILE = 4;
  }

  enum FileStatus {
    UNAVAILABLE = 0;
    SAME = 1;
    CHANGED = 2;
    ADDED = 3;
  }
}

message Measure {
  string metric_key = 1;
  oneof value {
    BoolValue boolean_value = 2;
    IntValue int_value = 3;
    LongValue long_value = 4;
    DoubleValue double_value = 5;
    StringValue string_value = 6;
  }

  message BoolValue {
    bool value = 1;
    string data = 2;
  }

  message IntValue {
    int32 value = 1;
    string data = 2;
  }

  message LongValue {
    int64 value = 1;
    string data = 2;
  }

  message DoubleValue {
    double value = 1;
    string data = 2;
  }

  message StringValue {
    string value = 1;
  }
}

message Issue {
  string rule_repository = 1;
  string rule_key = 2;
  // Only when issue component is a file. Can also be empty for a file if this is an issue global to the file.
  string msg = 3;
  optional Severity overriddenSeverity = 4;
  double gap = 5;
  // Only when issue component is a file. Can also be empty for a file if this is an issue global to the file.
  // Will be identical to the first location of the first flow
  TextRange text_range = 6;
  repeated Flow flow = 7;
  bool quickFixAvailable = 8;
  optional string ruleDescriptionContextKey = 9;
  repeated MessageFormatting msgFormatting = 10;
  repeated string codeVariants = 11;
  repeated Impact overriddenImpacts = 12;
}

message ExternalIssue {
  string engine_id = 1;
  string rule_id = 2;
  string msg = 3;
  optional Severity severity = 4;
  int64 effort = 5;
  TextRange text_range = 6;
  repeated Flow flow = 7;
  optional IssueType type = 8;
  repeated MessageFormatting msgFormatting = 9;
  repeated Impact impacts = 10;
  optional string cleanCodeAttribute = 11;
}

message AdHocRule {
  string engine_id = 1;
  string rule_id = 2;
  string name = 3;
  string description = 4;
  optional Severity severity = 5;
  optional IssueType type = 6;
  optional string cleanCodeAttribute = 7;
  repeated Impact defaultImpacts = 8;
}

enum IssueType {
  UNSET = 0;
  CODE_SMELL = 1;
  BUG = 2;
  VULNERABILITY = 3;
  SECURITY_HOTSPOT = 4;
}

message IssueLocation {
  int32 component_ref = 1;
  // Only when component is a file. Can be empty for a file if this is an issue global to the file.
  TextRange text_range = 2;
  string msg = 3;
  repeated MessageFormatting msgFormatting = 4;
}

message MessageFormatting {
  int32 start = 1;
  int32 end = 2;
  MessageFormattingType type = 3;
}

enum MessageFormattingType {
  CODE = 0;
}

message Flow {
  repeated IssueLocation location = 1;
  string description = 2;
  FlowType type = 3;
}

enum FlowType {
  UNDEFINED = 0;
  DATA = 1;
  EXECUTION = 2;
}

message Changesets {
  int32 component_ref = 1;
  // If set to true then it means changeset attribute is empty and compute engine should copy data from previous analysis
  bool copy_from_previous = 2;
  repeated Changeset changeset = 3;
  // if changesetIndexByLine[5] = 2 then it means that changeset[2] is the last one on line 6
  repeated int32 changesetIndexByLine = 4 [packed = true];

  message Changeset {
    string revision = 1;
    string author = 2;
    int64 date = 3;
  }
}

message Duplicate {
  // Will be 0 when duplicate is in the same file
  int32 other_file_ref = 1;
  // Only start_line and end_line are provided since we dont support "precise" duplication location.
  TextRange range = 2;
}

message Duplication {
  // Origin position in current file. Only start_line and end_line are provided since we dont support "precise" duplication location.
  TextRange origin_position = 1;
  repeated Duplicate duplicate = 2;
}

// Used for cross project duplication
message CpdTextBlock {
  string hash = 1;
  int32 start_line = 2;
  int32 end_line = 3;
  int32 start_token_index = 4;
  int32 end_token_index = 5;
}

// Lines start at 1 and line offsets start at 0
message TextRange {
  int32 start_line = 1;
  // End line (inclusive)
  int32 end_line = 2;
  int32 start_offset = 3;
  int32 end_offset = 4;
}

message LineSgnificantCode {
  int32 line = 1;
  int32 start_offset = 2;
  int32 end_offset = 3;
}

message ChangedLines {
  repeated int32 line = 1;
}

message Symbol {
  TextRange declaration = 1;
  repeated TextRange reference = 2;
}

// Only FILE component has coverage information, and only executable lines should contains this information.
message LineCoverage {
  int32 line = 1;

  // Number of conditions to cover (if set, the value must be greater than 0)
  int32 conditions = 2;
  // Is the line has been touched by a unit test ? Returning false means that no test has touched this executable line.
  oneof has_hits {
    bool hits = 3;
  }
  // Number of conditions covered by tests
  oneof has_covered_conditions {
    int32 covered_conditions = 5;
  }
}

// Must be sorted by line and start offset
message SyntaxHighlightingRule {
  TextRange range = 1;
  HighlightingType type = 2;

  enum HighlightingType {
    UNSET = 0;
    ANNOTATION = 1;
    CONSTANT = 2;
    COMMENT = 3;
    STRUCTURED_COMMENT = 5;
    KEYWORD = 6;
    HIGHLIGHTING_STRING = 7;
    KEYWORD_LIGHT = 8;
    PREPROCESS_DIRECTIVE = 9;
  }
}

message AnalysisWarning {
  string text = 1;
  int64 timestamp = 2;
}

message Impact {
  SoftwareQuality software_quality = 1;
  ImpactSeverity severity = 2;
}

enum ImpactSeverity {
  // Zero is required in order to not get first entry as a default value
  // See http://androiddevblog.com/protocol-buffers-pitfall-adding-enum-values/
  ImpactSeverity_UNKNOWN_IMPACT_SEVERITY = 0;
  ImpactSeverity_LOW = 1;
  ImpactSeverity_MEDIUM = 2;
  ImpactSeverity_HIGH = 3;
  // INFO and BLOCKER conflicts with Severity enum, so we use different values prefixed with enum name
  // See https://github.com/protocolbuffers/protobuf/issues/5425
  ImpactSeverity_INFO = 4;
  ImpactSeverity_BLOCKER = 5;
}

enum SoftwareQuality {
  // Zero is required in order to not get first entry as a default value
  // See http://androiddevblog.com/protocol-buffers-pitfall-adding-enum-values/
  UNKNOWN_IMPACT_QUALITY = 0;
  MAINTAINABILITY = 1;
  RELIABILITY = 2;
  SECURITY = 3;
}

message Dependency {
  string key = 1;
  string name = 2;
  optional string package_manager = 3;
  optional string full_name = 4;
  optional string description = 5;
  optional string version = 6;
  repeated string parent_dependency_key = 7;
}