blob: 08595575dd81c01b31504abe34a50c82d1abaf7f [file] [log] [blame]
dslomovf1296572017-08-22 16:29:06 +02001// Copyright 2017 The Bazel Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.lib.packages;
15
Googlerd327b802023-06-06 16:51:36 -070016import static com.google.common.base.MoreObjects.firstNonNull;
17
dslomovf1296572017-08-22 16:29:06 +020018import com.google.common.collect.ImmutableCollection;
adonovan121224e2020-05-18 08:39:45 -070019import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
adonovandd000462020-11-06 12:57:38 -080020import javax.annotation.Nullable;
adonovan450c7ad2020-09-14 13:00:21 -070021import net.starlark.java.eval.EvalException;
22import net.starlark.java.eval.Starlark;
23import net.starlark.java.eval.StarlarkSemantics;
24import net.starlark.java.syntax.Location;
dslomovf1296572017-08-22 16:29:06 +020025
adonovan7202d102019-12-09 13:58:57 -080026/**
27 * Abstract base class for implementations of {@link StructImpl} that expose
adonovan121224e2020-05-18 08:39:45 -070028 * StarlarkCallable-annotated fields (not just methods) to Starlark code. Subclasses must be
29 * immutable.
adonovan7202d102019-12-09 13:58:57 -080030 */
adonovandd000462020-11-06 12:57:38 -080031// TODO(adonovan): ensure that all subclasses are named *Info and not *Provider.
32// (Info is to object as Provider is to class.)
adonovan121224e2020-05-18 08:39:45 -070033@Immutable
adonovan7202d102019-12-09 13:58:57 -080034public abstract class NativeInfo extends StructImpl {
dslomovf1296572017-08-22 16:29:06 +020035
Googlerd327b802023-06-06 16:51:36 -070036 private final Location location;
37
adonovandd000462020-11-06 12:57:38 -080038 protected NativeInfo() {
39 this(Location.BUILTIN);
adonovan7202d102019-12-09 13:58:57 -080040 }
41
adonovandd000462020-11-06 12:57:38 -080042 // TODO(adonovan): most subclasses pass Location.BUILTIN most of the time.
43 // Make only those classes that pass a real location pay for it.
Googlerd327b802023-06-06 16:51:36 -070044 protected NativeInfo(@Nullable Location location) {
45 this.location = firstNonNull(location, Location.BUILTIN);
46 }
47
48 @Override
49 public final Location getCreationLocation() {
50 return location;
adonovan7202d102019-12-09 13:58:57 -080051 }
cparsons6c1c0662018-02-05 02:01:28 -080052
adonovan121224e2020-05-18 08:39:45 -070053 @Override
54 public boolean isImmutable() {
55 return true; // immutable and Starlark-hashable
56 }
57
Googler15a700c2019-11-27 12:45:29 -080058 // TODO(adonovan): logically this should be a parameter of getValue
59 // and getFieldNames or an instance field of this object.
adonovanb85d0b72020-05-08 11:59:19 -070060 private static final StarlarkSemantics SEMANTICS = StarlarkSemantics.DEFAULT;
Googler15a700c2019-11-27 12:45:29 -080061
Googler3d50c6a2022-07-06 03:50:04 -070062 @Nullable
dslomovf1296572017-08-22 16:29:06 +020063 @Override
cparsons6c1c0662018-02-05 02:01:28 -080064 public Object getValue(String name) throws EvalException {
adonovan29535e02020-07-28 20:45:35 -070065 // TODO(adonovan): this seems unnecessarily complicated:
66 // Starlark's x.name and getattr(x, name) already check the
67 // annotated fields/methods first, so there's no need to handle them here.
68 // Similarly, Starlark.dir checks annotated fields/methods first, so
69 // there's no need for getFieldNames to report them.
70 // The only code that would notice any difference is direct Java
71 // calls to getValue/getField names; they should instead
72 // use getattr and dir. However, dir does report methods,
73 // not just fields.
74
gregce8345b792020-05-15 13:23:29 -070075 // @StarlarkMethod(structField=true) -- Java field
adonovane71be212019-12-06 10:07:32 -080076 if (getFieldNames().contains(name)) {
cparsons48032932018-04-18 09:39:02 -070077 try {
adonovan29535e02020-07-28 20:45:35 -070078 return Starlark.getAnnotatedField(SEMANTICS, this, name);
cparsons48032932018-04-18 09:39:02 -070079 } catch (InterruptedException exception) {
80 // Struct fields on NativeInfo objects are supposed to behave well and not throw
81 // exceptions, as they should be logicless field accessors. If this occurs, it's
82 // indicative of a bad NativeInfo implementation.
83 throw new IllegalStateException(
adonovane71be212019-12-06 10:07:32 -080084 String.format(
85 "Access of field %s was unexpectedly interrupted, but should be "
86 + "uninterruptible. This is indicative of a bad provider implementation.",
87 name));
cparsons48032932018-04-18 09:39:02 -070088 }
cparsons6c1c0662018-02-05 02:01:28 -080089 }
adonovane71be212019-12-06 10:07:32 -080090 return null;
dslomovf1296572017-08-22 16:29:06 +020091 }
92
93 @Override
brandjond331fa72017-12-28 07:38:31 -080094 public ImmutableCollection<String> getFieldNames() {
adonovan29535e02020-07-28 20:45:35 -070095 return Starlark.getAnnotatedFieldNames(SEMANTICS, this);
dslomovf1296572017-08-22 16:29:06 +020096 }
dslomovf1296572017-08-22 16:29:06 +020097}