Introduce TreeArtifact and associated code to work with it. No functionality implemented yet.

--
MOS_MIGRATED_REVID=114157140
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisEnvironment.java b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisEnvironment.java
index f739246..bf02139 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisEnvironment.java
@@ -70,6 +70,13 @@
       Root root);
 
   /**
+   * Returns the artifact for the derived TreeArtifact with directory {@code rootRelativePath},
+   * creating it if necessary, and setting the root of that artifact to
+   * {@code root}. The artifact will be a TreeArtifact.
+   */
+  Artifact getTreeArtifact(PathFragment rootRelativePath, Root root);
+
+  /**
    * Returns the artifact for the derived file {@code rootRelativePath},
    * creating it if necessary, and setting the root of that artifact to
    * {@code root}. The artifact will represent the output directory of a {@code Fileset}.
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/CachingAnalysisEnvironment.java b/src/main/java/com/google/devtools/build/lib/analysis/CachingAnalysisEnvironment.java
index bfdd8b9..4d1d787 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/CachingAnalysisEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/CachingAnalysisEnvironment.java
@@ -231,6 +231,14 @@
   }
 
   @Override
+  public Artifact getTreeArtifact(PathFragment rootRelativePath, Root root) {
+    Preconditions.checkState(enabled);
+    return trackArtifactAndOrigin(
+        artifactFactory.getTreeArtifact(rootRelativePath, root, getOwner()),
+        extendedSanityChecks ? new Throwable() : null);
+  }
+
+  @Override
   public Artifact getFilesetArtifact(PathFragment rootRelativePath, Root root) {
     Preconditions.checkState(enabled);
     return trackArtifactAndOrigin(
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
index 68b54e8..f0fecff 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
@@ -562,6 +562,21 @@
         rootRelativePath, getPackageDirectory(), getLabel());
     return getAnalysisEnvironment().getDerivedArtifact(rootRelativePath, root);
   }
+
+  /**
+   * Creates a TreeArtifact under a given root with the given root-relative path.
+   *
+   * <p>Verifies that it is in the root-relative directory corresponding to the package of the rule,
+   * thus ensuring that it doesn't clash with other artifacts generated by other rules using this
+   * method.
+   */
+  public Artifact getTreeArtifact(PathFragment rootRelativePath, Root root) {
+    Preconditions.checkState(rootRelativePath.startsWith(getPackageDirectory()),
+        "Output artifact '%s' not under package directory '%s' for target '%s'",
+        rootRelativePath, getPackageDirectory(), getLabel());
+    return getAnalysisEnvironment().getTreeArtifact(rootRelativePath, root);
+  }
+
   /**
    * Creates an artifact in a directory that is unique to the rule, thus guaranteeing that it never
    * clashes with artifacts created by other rules.