// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// This file contains the protocol buffer representation of a build
// file or 'blaze query --output=proto' call.

syntax = "proto2";

package blaze_query;

// option cc_api_version = 2;
// option java_api_version = 1;
option java_package = "com.google.devtools.build.lib.query2.proto.proto2api";

message License {
  repeated string license_type = 1;
  repeated string exception = 2;
}

message StringDictEntry {
  required string key = 1;
  required string value = 2;
}

message LabelDictUnaryEntry {
  required string key = 1;
  required string value = 2;
}

message LabelListDictEntry {
  required string key = 1;
  repeated string value = 2;
}

message LabelKeyedStringDictEntry {
  required string key = 1;
  required string value = 2;
}

message StringListDictEntry {
  required string key = 1;
  repeated string value = 2;
}

// Represents an entry attribute of a Fileset rule in a build file.
message FilesetEntry {
  // Indicates what to do when a source file is actually a symlink.
  enum SymlinkBehavior {
    COPY = 1;
    DEREFERENCE = 2;
  }

  // The label pointing to the source target where files are copied from.
  required string source = 1;

  // The relative path within the fileset rule where files will be mapped.
  required string destination_directory = 2;

  // Whether the files= attribute was specified. This is necessary because
  // no files= attribute and files=[] mean different things.
  optional bool files_present = 7;

  // A list of file labels to include from the source directory.
  repeated string file = 3;

  // If this is a fileset entry representing files within the rule
  // package, this lists relative paths to files that should be excluded from
  // the set.  This cannot contain values if 'file' also has values.
  repeated string exclude = 4;

  // This field is optional because there will be some time when the new
  // PB is used by tools depending on blaze query, but the new blaze version
  // is not yet released.
  // TODO(bazel-team): Make this field required once a version of Blaze is
  // released that outputs this field.
  optional SymlinkBehavior symlink_behavior = 5 [default = COPY];

  // The prefix to strip from the path of the files in this FilesetEntry. Note
  // that no value and the empty string as the value mean different things here.
  optional string strip_prefix = 6;
}

// A rule attribute. Each attribute must have a type and one of the various
// value fields populated - for the most part.
//
// Attributes of BOOLEAN and TRISTATE type may set all of the int, bool, and
// string values for backwards compatibility with clients that expect them to
// be set.
//
// Attributes of INTEGER, STRING, LABEL, LICENSE, BOOLEAN, and TRISTATE type
// may set *none* of the values. This can happen if the Attribute message is
// prepared for a client that doesn't support SELECTOR_LIST, but the rule has
// a selector list value for the attribute. (Selector lists for attributes of
// other types--the collection types--are handled differently when prepared
// for such a client. The possible collection values are gathered together
// and flattened.)
//
// By checking the type, the appropriate value can be extracted - see the
// comments on each type for the associated value.  The order of lists comes
// from the blaze parsing. If an attribute is of a list type, the associated
// list should never be empty.
message Attribute {
  reserved 12, 16;

  // Indicates the type of attribute.
  enum Discriminator {
    INTEGER = 1;              // int_value
    STRING = 2;               // string_value
    LABEL = 3;                // string_value
    OUTPUT = 4;               // string_value
    STRING_LIST = 5;          // string_list_value
    LABEL_LIST = 6;           // string_list_value
    OUTPUT_LIST = 7;          // string_list_value
    DISTRIBUTION_SET = 8;     // string_list_value - order is unimportant
    LICENSE = 9;              // license
    STRING_DICT = 10;         // string_dict_value
    FILESET_ENTRY_LIST = 11;  // fileset_list_value
    LABEL_LIST_DICT = 12;     // label_list_dict_value
    STRING_LIST_DICT = 13;    // string_list_dict_value
    BOOLEAN = 14;             // int, bool and string value
    TRISTATE = 15;            // tristate, int and string value
    INTEGER_LIST = 16;        // int_list_value
    UNKNOWN = 18;             // unknown type, use only for build extensions
    LABEL_DICT_UNARY = 19;    // label_dict_unary_value
    SELECTOR_LIST = 20;       // selector_list
    LABEL_KEYED_STRING_DICT = 21;  // label_keyed_string_dict

    DEPRECATED_STRING_DICT_UNARY = 17;
  }

  // Values for the TriState field type.
  enum Tristate {
    NO = 0;
    YES = 1;
    AUTO = 2;
  }

  message SelectorEntry {
    reserved 12;

    // The key of the selector entry. At this time, this is the label of a
    // config_setting rule, or the pseudo-label "//conditions:default".
    optional string label = 1;

    // True if the entry's value is the default value for the type as a
    // result of the condition value being specified as None (ie:
    // {"//condition": None}).
    optional bool is_default_value = 16;

    // Exactly one of the following fields (except for glob_criteria) must be
    // populated - note that the BOOLEAN and TRISTATE caveat in Attribute's
    // comment does not apply here. The type field in the SelectorList
    // containing this entry indicates which of these fields is populated,
    // in accordance with the comments on Discriminator enum values above.
    // (To be explicit: BOOLEAN populates the boolean_value field and TRISTATE
    // populates the tristate_value field.)
    optional int32 int_value = 2;
    optional string string_value = 3;
    optional bool boolean_value = 4;
    optional Tristate tristate_value = 5;
    repeated string string_list_value = 6;
    optional License license = 7;
    repeated StringDictEntry string_dict_value = 8;
    repeated FilesetEntry fileset_list_value = 9;
    repeated LabelListDictEntry label_list_dict_value = 10;
    repeated StringListDictEntry string_list_dict_value = 11;
    repeated int32 int_list_value = 13;
    repeated LabelDictUnaryEntry label_dict_unary_value = 15;
    repeated LabelKeyedStringDictEntry label_keyed_string_dict_value = 17;

    repeated bytes DEPRECATED_string_dict_unary_value = 14;
  }

  message Selector {
    // The list of (label, value) pairs in the map that defines the selector.
    // At this time, this cannot be empty, i.e. a selector has at least one
    // entry.
    repeated SelectorEntry entries = 1;

    // Whether or not this has any default values.
    optional bool has_default_value = 2;

    // The error message when no condition matches.
    optional string no_match_error = 3;
  }

  message SelectorList {
    // The type that this selector list evaluates to, and the type that each
    // selector in the list evaluates to. At this time, this cannot be
    // SELECTOR_LIST, i.e. selector lists do not nest.
    optional Discriminator type = 1;

    // The list of selector elements in this selector list. At this time, this
    // cannot be empty, i.e. a selector list is never empty.
    repeated Selector elements = 2;
  }

  // The name of the attribute
  required string name = 1;

  // Whether the attribute was explicitly specified
  optional bool explicitly_specified = 13;

  // If this attribute has a string value or a string list value, then this
  // may be set to indicate that the value may be treated as a label that
  // isn't a dependency of this attribute's rule.
  optional bool nodep = 20;

  // The type of attribute.  This message is used for all of the different
  // attribute types so the discriminator helps for figuring out what is
  // stored in the message.
  required Discriminator type = 2;

  // If this attribute has an integer value this will be populated.
  // Boolean and TriState also use this field as [0,1] and [-1,0,1]
  // for [false, true] and [auto, no, yes] respectively.
  optional int32 int_value = 3;

  // If the attribute has a string value this will be populated.  Label and
  // path attributes use this field as the value even though the type may
  // be LABEL or something else other than STRING.
  optional string string_value = 5;

  // If the attribute has a boolean value this will be populated.
  optional bool boolean_value = 14;

  // If the attribute is a Tristate value, this will be populated.
  optional Tristate tristate_value = 15;

  // The value of the attribute has a list of string values (label and path
  // note from STRING applies here as well).
  repeated string string_list_value = 6;

  // If this is a license attribute, the license information is stored here.
  optional License license = 7;

  // If this is a string dict, each entry will be stored here.
  repeated StringDictEntry string_dict_value = 8;

  // If the attribute is part of a Fileset, the fileset entries are stored in
  // this field.
  repeated FilesetEntry fileset_list_value = 9;

  // If this is a label list dict, each entry will be stored here.
  repeated LabelListDictEntry label_list_dict_value = 10;

  // If this is a string list dict, each entry will be stored here.
  repeated StringListDictEntry string_list_dict_value = 11;

  // The value of the attribute has a list of int32 values
  repeated int32 int_list_value = 17;

  // If this is a label dict unary, each entry will be stored here.
  repeated LabelDictUnaryEntry label_dict_unary_value = 19;

  // If this is a label-keyed string dict, each entry will be stored here.
  repeated LabelKeyedStringDictEntry label_keyed_string_dict_value = 22;

  // If this attribute's value is an expression containing one or more select
  // expressions, then its type is SELECTOR_LIST and a SelectorList will be
  // stored here.
  optional SelectorList selector_list = 21;

  repeated bytes DEPRECATED_string_dict_unary_value = 18;
}

// A rule instance (e.g., cc_library foo, java_binary bar).
message Rule {
  reserved 8, 11;

  // The name of the rule (formatted as an absolute label, e.g. //foo/bar:baz).
  required string name = 1;

  // The rule class (e.g., java_library)
  required string rule_class = 2;

  // The BUILD file and line number of the location (formatted as
  // <absolute_path>:<line_number>:<column_number>) in the rule's package's
  // BUILD file where the rule instance was instantiated. The line number will
  // be that of a rule invocation or macro call (that in turn invoked a
  // rule). See
  // https://docs.bazel.build/versions/master/skylark/macros.html#macro-creation
  optional string location = 3;

  // All of the attributes that describe the rule.
  repeated Attribute attribute = 4;

  // All of the inputs to the rule (formatted as absolute labels). These are
  // predecessors in the dependency graph.
  repeated string rule_input = 5;

  // All of the outputs of the rule (formatted as absolute labels). These are
  // successors in the dependency graph.
  repeated string rule_output = 6;

  // The set of all "features" inherited from the rule's package declaration.
  repeated string default_setting = 7;

  // The rule's class's public by default value.
  optional bool DEPRECATED_public_by_default = 9;

  optional bool DEPRECATED_is_skylark = 10;

  // Hash encapsulating the behavior of this Starlark rule. Any change to this
  // rule's definition that could change its behavior will be reflected here.
  optional string skylark_environment_hash_code = 12;

  // The Starlark call stack at the moment the rule was instantiated.
  // Each entry has the form "file:line:col: function".
  // The outermost stack frame ("<toplevel>", the BUILD file) appears first;
  // the frame for the rule function itself is omitted.
  // The file name may be relative to package's source root directory.
  //
  // Requires --proto:instantiation_stack=true.
  repeated string instantiation_stack = 13;

  // The Starlark call stack for the definition of the rule class of this
  // particular rule instance. If empty, either populating the field was not
  // enabled on the command line with the --proto:definition_stack flag or the
  // rule is a native one.
  repeated string definition_stack = 14;
}

// Summary of all transitive dependencies of 'rule,' where each dependent
// rule is included only once in the 'dependency' field.  Gives complete
// information to analyze the single build target labeled rule.name,
// including optional location of target in BUILD file.
message RuleSummary {
  required Rule rule = 1;
  repeated Rule dependency = 2;
  optional string location = 3;
}

// A package group. Aside from the name, it contains the list of packages
// present in the group (as specified in the BUILD file).
message PackageGroup {
  reserved 4;

  // The name of the package group
  required string name = 1;

  // The list of packages as specified in the BUILD file. Currently this is
  // only a list of packages, but some time in the future, there might be
  // some type of wildcard mechanism.
  repeated string contained_package = 2;

  // The list of sub package groups included in this one.
  repeated string included_package_group = 3;
}

// An environment group.
message EnvironmentGroup {
  // The name of the environment group.
  required string name = 1;

  // The environments that belong to this group (as labels).
  repeated string environment = 2;

  // The member environments that rules implicitly support if not otherwise
  // specified.
  repeated string default = 3;
}

// A file that is an input into the build system.
// Next-Id: 10
message SourceFile {
  reserved 7;

  // The name of the source file (a label).
  required string name = 1;

  // The location of the source file.  This is a path with a line number and a
  // column number not a label in the build system.
  optional string location = 2;

  // Labels of .bzl (Starlark) files that are transitively loaded in this BUILD
  // file. This is present only when the SourceFile represents a BUILD file that
  // loaded .bzl files.
  // TODO(bazel-team): Rename this field.
  repeated string subinclude = 3;

  // Labels of package groups that are mentioned in the visibility declaration
  // for this source file.
  repeated string package_group = 4;

  // Labels mentioned in the visibility declaration (including :__pkg__ and
  // //visibility: ones)
  repeated string visibility_label = 5;

  // The package-level features enabled for this package. Only present if the
  // SourceFile represents a BUILD file.
  repeated string feature = 6;

  // License attribute for the file.
  optional License license = 8;

  // True if the package contains an error. Only present if the SourceFile
  // represents a BUILD file.
  optional bool package_contains_errors = 9;
}

// A file that is the output of a build rule.
message GeneratedFile {
  // The name of the generated file (a label).
  required string name = 1;

  // The label of the target that generates the file.
  required string generating_rule = 2;

  // The path, line number, and column number of the output file (not a label).
  optional string location = 3;
}

// A target from a blaze query execution.  Similar to the Attribute message,
// the Discriminator is used to determine which field contains information.
// For any given type, only one of these can be populated in a single Target.
message Target {
  enum Discriminator {
    RULE = 1;
    SOURCE_FILE = 2;
    GENERATED_FILE = 3;
    PACKAGE_GROUP = 4;
    ENVIRONMENT_GROUP = 5;
  }

  // The type of target contained in the message.
  required Discriminator type = 1;

  // If this target represents a rule, the rule is stored here.
  optional Rule rule = 2;

  // A file that is not generated by the build system (version controlled
  // or created by the test harness).
  optional SourceFile source_file = 3;

  // A generated file that is the output of a rule.
  optional GeneratedFile generated_file = 4;

  // A package group.
  optional PackageGroup package_group = 5;

  // An environment group.
  optional EnvironmentGroup environment_group = 6;
}

// Container for all of the blaze query results.
message QueryResult {
  // All of the targets returned by the blaze query.
  repeated Target target = 1;
}

////////////////////////////////////////////////////////////////////////////
// Messages dealing with querying the BUILD language itself. For now, this is
// quite simplistic: Blaze can only tell the names of the rule classes, their
// attributes with their type.

// Information about allowed rule classes for a specific attribute of a rule.
message AllowedRuleClassInfo {
  enum AllowedRuleClasses {
    ANY = 1;        // Any rule is allowed to be in this attribute
    SPECIFIED = 2;  // Only the explicitly listed rules are allowed
  }

  required AllowedRuleClasses policy = 1;

  // Rule class names of rules allowed in this attribute, e.g "cc_library",
  // "py_binary". Only present if the allowed_rule_classes field is set to
  // SPECIFIED.
  repeated string allowed_rule_class = 2;
}

// This message represents a single attribute of a single rule.
// See docs.bazel.build/versions/master/skylark/lib/attr.html.
message AttributeDefinition {
  required string name = 1;  // e.g. "name", "srcs"
  required Attribute.Discriminator type = 2;
  optional bool mandatory = 3;
  optional AllowedRuleClassInfo allowed_rule_classes = 4;  // type=label*
  optional string documentation = 5;
  optional bool allow_empty = 6;        // type=*_list|*_dict
  optional bool allow_single_file = 7;  // type=label
  optional AttributeValue default =
      9;  // simple (not computed/late-bound) values only
  optional bool executable = 10;  // type=label
  optional bool configurable = 11;
  optional bool nodep =
      12;  // label-valued edge does not establish a dependency
  optional bool cfg_is_host =
      13;  // edge entails a transition to "host" configuration
}

// An AttributeValue represents the value of an attribute.
// A single field, determined by the attribute type, is populated.
//
// It is used only for AttributeDefinition.default. Attribute and
// SelectorEntry do their own thing for unfortunate historical reasons.
message AttributeValue {
  optional int32 int = 1;            // type=int|tristate
  optional string string = 2;        // type=string|label|output
  optional bool bool = 3;            // type=bool
  repeated AttributeValue list = 4;  // type=*_list|distrib
  repeated DictEntry dict = 5;       // type=*_dict

  message DictEntry {
    required string key = 1;
    required AttributeValue value = 2;
  }
}

message RuleDefinition {
  required string name = 1;
  // Only contains documented attributes
  repeated AttributeDefinition attribute = 2;
  optional string documentation = 3;
  // Only for build extensions: label to file that defines the extension
  optional string label = 4;
}

message BuildLanguage {
  // Only contains documented rule definitions
  repeated RuleDefinition rule = 1;
}
