aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/cmdline/TargetPatternResolver.java
blob: 69d3b223f16062b8f0474f96bee9d35cb9095161 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// 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.

package com.google.devtools.build.lib.cmdline;

import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.devtools.build.lib.util.BatchCallback;
import com.google.devtools.build.lib.util.ThreadSafeBatchCallback;
import com.google.devtools.build.lib.vfs.PathFragment;

/**
 * A callback that is used during the process of converting target patterns (such as
 * <code>//foo:all</code>) into one or more lists of targets (such as <code>//foo:foo,
 * //foo:bar</code>). During a call to {@link TargetPattern#eval}, the {@link TargetPattern} makes
 * calls to this interface to implement the target pattern semantics. The generic type {@code T} is
 * only for compile-time type safety; there are no requirements to the actual type.
 */
public abstract class TargetPatternResolver<T> {

  /**
   * Reports the given warning.
   */
  public abstract void warn(String msg);

  /**
   * Returns a single target corresponding to the given label, or null. This method may only throw
   * an exception if the current thread was interrupted.
   */
  public abstract T getTargetOrNull(Label label) throws InterruptedException;

  /**
   * Returns a single target corresponding to the given label, or an empty or failed result.
   */
  public abstract ResolvedTargets<T> getExplicitTarget(Label label)
      throws TargetParsingException, InterruptedException;

  /**
   * Returns the set containing the targets found in the given package. The specified directory is
   * not necessarily a valid package name. If {@code rulesOnly} is true, then this method should
   * only return rules in the given package.
   *
   * @param originalPattern the original target pattern for error reporting purposes
   * @param packageIdentifier the identifier of the package
   * @param rulesOnly whether to return rules only
   */
  public abstract ResolvedTargets<T> getTargetsInPackage(String originalPattern,
      PackageIdentifier packageIdentifier, boolean rulesOnly)
      throws TargetParsingException, InterruptedException;

  /**
   * Computes the set containing the targets found below the given {@code directory}, passing it in
   * batches to {@code callback}. Conceptually, this method should look for all packages that start
   * with the {@code directory} (as a proper prefix directory, i.e., "foo/ba" is not a proper prefix
   * of "foo/bar/"), and then collect all targets in each such package (subject to
   * {@code rulesOnly}) as if calling {@link #getTargetsInPackage}. The specified directory is not
   * necessarily a valid package name.
   *
   * <p>Note that the {@code directory} can be empty, which corresponds to the "//..." pattern.
   * Implementations may choose not to support this case and throw an {@link
   * IllegalArgumentException} exception instead, or may restrict the set of directories that are
   * considered by default.
   *
   * <p>If the {@code directory} points to a package, then that package should also be part of the
   * result.
   *
   * @param originalPattern the original target pattern for error reporting purposes
   * @param directory the directory in which to look for packages
   * @param rulesOnly whether to return rules only
   * @param blacklistedSubdirectories a set of transitive subdirectories beneath {@code directory}
   *    to ignore
   * @param excludedSubdirectories another set of transitive subdirectories beneath
   *    {@code directory} to ignore
   * @param callback the callback to receive the result, possibly in multiple batches.
   * @param exceptionClass The class type of the parameterized exception.
   * @throws TargetParsingException under implementation-specific failure conditions
   */
  public abstract <E extends Exception> void findTargetsBeneathDirectory(
      RepositoryName repository,
      String originalPattern,
      String directory,
      boolean rulesOnly,
      ImmutableSet<PathFragment> blacklistedSubdirectories,
      ImmutableSet<PathFragment> excludedSubdirectories,
      BatchCallback<T, E> callback,
      Class<E> exceptionClass)
      throws TargetParsingException, E, InterruptedException;

  /**
   * Async version of {@link #findTargetsBeneathDirectory}
   *
   * <p>Default implementation is synchronous.
   */
  public <E extends Exception> ListenableFuture<Void> findTargetsBeneathDirectoryAsync(
      RepositoryName repository,
      String originalPattern,
      String directory,
      boolean rulesOnly,
      ImmutableSet<PathFragment> blacklistedSubdirectories,
      ImmutableSet<PathFragment> excludedSubdirectories,
      ThreadSafeBatchCallback<T, E> callback,
      Class<E> exceptionClass,
      ListeningExecutorService executor) {
      try {
        findTargetsBeneathDirectory(
            repository,
            originalPattern,
            directory,
            rulesOnly,
            blacklistedSubdirectories,
            excludedSubdirectories,
            callback,
            exceptionClass);
        return Futures.immediateFuture(null);
      } catch (TargetParsingException e) {
        return Futures.immediateFailedFuture(e);
      } catch (InterruptedException e) {
        return Futures.immediateCancelledFuture();
      } catch (Exception e) {
        if (exceptionClass.isInstance(e)) {
          return Futures.immediateFailedFuture(e);
        }
        throw new IllegalStateException(e);
      }
  }

  /**
   * Returns true, if and only if the given package identifier corresponds to a package, i.e., a
   * file with the name {@code packageName/BUILD} exists in the appropriate repository.
   */
  public abstract boolean isPackage(PackageIdentifier packageIdentifier)
      throws InterruptedException;

  /**
   * Returns the target kind of the given target, for example {@code cc_library rule}.
   */
  public abstract String getTargetKind(T target);
}