/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * 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.
 */
syntax = "proto3";

package ide_query;

option go_package = "ide_query/ide_query_proto";

message GeneratedFile {
  // Path to the file relative to build_out_dir.
  string path = 1;

  // The text of the generated file, if not provided contents will be read
  // from the path above in user's workstation.
  optional bytes contents = 2;
}

message IdeAnalysis {
  // Directory that contains build outputs generated by the build system.
  // Relative to repository root.
  string build_out_dir = 1;
  // Working directory used by the build system.
  // Relative to repository root.
  string working_dir = 4;
  // Only set if the whole query failed.
  optional AnalysisError error = 5;
  // List of results, one per queried file.
  repeated AnalysisResult results = 6;
  // List of buildable units directly or indirectly references by the results.
  repeated BuildableUnit units = 7;

  reserved 2, 3;
}

message AnalysisError {
  // Human readable error message.
  string error_message = 1;
}

message AnalysisResult {
  // Path to the source file that was queried, relative to repository root.
  string source_file_path = 1;
  // Indicates the success/failure for the query.
  message Status {
    enum Code {
      CODE_UNSPECIFIED = 0;
      CODE_OK = 1;
      CODE_NOT_FOUND = 2;  // no target or module found for the source file.
      CODE_BUILD_FAILED = 3;
    }
    Code code = 1;
    // Details about the status, might be displayed to user.
    optional string status_message = 2;
  }
  // Represents status for this result. e.g. not part of the build graph.
  Status status = 2;
  // ID of buildable unit that contains the source file.
  // The ide_query script can choose the most relevant unit from multiple
  // options.
  string unit_id = 3;
  // Invalidation rule to check if the result is still valid.
  Invalidation invalidation = 4;
}

enum Language {
  LANGUAGE_UNSPECIFIED = 0;
  LANGUAGE_JAVA = 1;  // also includes Kotlin
  LANGUAGE_CPP = 2;
}

message BuildableUnit {
  // Unique identifier of the buildable unit.
  //
  // Examples:
  //   - Java: module or target name, e.g. "framework-bluetooth" or
  //   "//third_party/hamcrest:hamcrest_java"
  //   - C++: source file, e.g. "path/to/file.cc"
  string id = 1;
  // Language of the unit.
  // Required for buildable units directly referenced by the AnalysisResult,
  // e.g. the unit associated with the compilation stage for the source file.
  Language language = 2;
  // Source files that are part of this unit.
  // Path to the file relative to working_dir.
  repeated string source_file_paths = 3;
  // Compiler arguments to compile the source files.
  repeated string compiler_arguments = 4;
  // List of generated files produced by this unit.
  repeated GeneratedFile generated_files = 5;
  // List of other BuildableUnits this unit depend on.
  repeated string dependency_ids = 6;
}

// Invalidation rule to check if the result is still valid.
// This should contain files/dirs that are not directly part of the build graph
// but still affect the result. For example BUILD files, directory to the
// toolchain or config files etc.
message Invalidation {
  // If any of these files change the result may become invalid.
  // Path to the file relative to repository root.
  repeated string file_paths = 1;

  message Wildcard {
    // Prefix of the file path (e.g. "path/to/")
    optional string prefix = 1;
    // Suffix of the file path (e.g. "Android.bp")
    optional string suffix = 2;
    // If false, the part of the path between the given `prefix` and `suffix`
    // should not contain directory separators ('/').
    optional bool can_cross_folder = 3;
  }
  // If any of these rules match a changed file the result may become invalid.
  repeated Wildcard wildcards = 4;
}