aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkCallable.java
blob: 7bc40efef5089961c3ccf6b359642dc17b5dc1f8 (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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// 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.skylarkinterface;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Annotates a Java method that can be called from Skylark.
 *
 * <p>This annotation is only allowed to appear on methods of classes that are directly annotated
 * with {@link SkylarkModule} or {@link SkylarkGlobalLibrary}. Since subtypes can't add new
 * Skylark-accessible methods unless they have their own {@code @SkylarkModule} annotation, this
 * implies that you can always determine the complete set of Skylark entry points for a given {@link
 * SkylarkValue} type by looking at the ancestor class or interface from which it inherits its
 * {@code @SkylarkModule}.
 *
 * <p>If a method is annotated with {@code @SkylarkCallable}, it is not allowed to have any
 * overloads or hide any static or default methods. Overriding is allowed, but the {@code
 * @SkylarkCallable} annotation itself must not be repeated on the override. This ensures that given
 * a method, we can always determine its corresponding {@code @SkylarkCallable} annotation, if it
 * has one, by scanning all methods of the same name in its class hierarchy, without worrying about
 * complications like overloading or generics. The lookup functionality is implemented by {@link
 * SkylarkInterfaceUtils#getSkylarkCallable}.
 *
 * <p>Methods having this annotation are required to satisfy the following (enforced by an
 * annotation processor):
 *
 * <ul>
 *   <li>The method must be public.
 *   <li>If structField=true, there must be zero user-supplied parameters.
 *   <li>The underlying java method's parameters must be supplied in the following order:
 *       <pre>method([positionals]*[named args]*(extra positionals list)(extra kwargs)
 *       (Location)(FuncallExpression)(Envrionment)(SkylarkSemantics))</pre>
 *       where (extra positionals list) is a SkylarkList if extraPositionals is defined, (extra
 *       kwargs) is a SkylarkDict if extraKeywords is defined, and Location, FuncallExpression,
 *       Environment, and SkylarkSemantics are supplied by the interpreter if and only if
 *       useLocation, useAst, useEnvironment, and useSkylarkSemantics are specified, respectively.
 *   <li>The number of method parameters much match the number of annotation-declared parameters
 *       plus the number of interpreter-supplied parameters.
 * </ul>
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface SkylarkCallable {

  /**
   * Name of the method, as exposed to Skylark.
   */
  String name();

  /**
   * The documentation text in Skylark. It can contain HTML tags for special formatting.
   *
   * <p>It is allowed to be empty only if {@link #documented()} is false.
   */
  String doc() default "";

  /**
   * If true, the function will appear in the Skylark documentation. Set this to false if the
   * function is experimental or an overloading and doesn't need to be documented.
   */
  boolean documented() default true;

  /**
   * If true, this method will be considered as a field of the enclosing Java object. E.g., if set
   * to true on a method {@code foo}, then the callsites of this method will look like {@code
   * bar.foo} instead of {@code bar.foo()}. The annotated method must be parameterless and {@link
   * #parameters()} should be empty.
   */
  boolean structField() default false;

  /**
   * List of parameters this function accepts.
   */
  Param[] parameters() default {};

  /**
   * Defines a catch-all list for additional unspecified positional parameters.
   *
   * <p>If this is left as default, it is an error for the caller to pass more positional arguments
   * than are explicitly allowed by the method signature. If this is defined, all additional
   * positional arguments are passed as elements of a {@link SkylarkList} to the method.
   *
   * <p>See python's <code>*args</code> (http://thepythonguru.com/python-args-and-kwargs/).
   *
   * <p>(If this is defined, the annotated method signature must contain a corresponding SkylarkList
   * parameter. See the interface-level javadoc for details.)
   */
  Param extraPositionals() default @Param(name = "");

  /**
   * Defines a catch-all dictionary for additional unspecified named parameters.
   *
   * <p>If this is left as default, it is an error for the caller to pass any named arguments not
   * explicitly declared by the method signature. If this is defined, all additional named arguments
   * are passed as elements of a {@link SkylarkDict} to the method.
   *
   * <p>See python's <code>**kwargs</code> (http://thepythonguru.com/python-args-and-kwargs/).
   *
   * <p>(If this is defined, the annotated method signature must contain a corresponding SkylarkDict
   * parameter. See the interface-level javadoc for details.)
   */
  Param extraKeywords() default @Param(name = "");

  /**
   * If true, indicates that the class containing the annotated method has the ability to be called
   * from skylark (as if it were a function) and that the annotated method should be invoked when
   * this occurs.
   *
   * <p>A class may only have one method with selfCall set to true.</p>
   *
   * <p>A method with selfCall=true must not be a structField, and must have name specified
   * (used for descriptive errors if, for example, there are missing arguments).</p>
   */
  boolean selfCall() default false;

  /**
   * Set it to true if the Java method may return <code>null</code> (which will then be converted to
   * <code>None</code>). If not set and the Java method returns null, an error will be raised.
   */
  boolean allowReturnNones() default false;

  /**
   * If true, the location of the call site will be passed as an argument of the annotated function.
   * (Thus, the annotated method signature must contain Location as a parameter. See the
   * interface-level javadoc for details.)
   *
   * <p>This is incompatible with structField=true. If structField is true, this must be false.
   */
  boolean useLocation() default false;

  /**
   * If true, the AST of the call site will be passed as an argument of the annotated function.
   * (Thus, the annotated method signature must contain FuncallExpression as a parameter. See the
   * interface-level javadoc for details.)
   *
   * <p>This is incompatible with structField=true. If structField is true, this must be false.
   */
  boolean useAst() default false;

  /**
   * If true, the Skylark Environment will be passed as an argument of the annotated function.
   * (Thus, the annotated method signature must contain Environment as a parameter. See the
   * interface-level javadoc for details.)
   *
   * <p>This is incompatible with structField=true. If structField is true, this must be false.
   */
  boolean useEnvironment() default false;

  /**
   * If true, the Skylark semantics will be passed as an argument of the annotated function. (Thus,
   * the annotated method signature must contain SkylarkSemantics as a parameter. See the
   * interface-level javadoc for details.)
   */
  boolean useSkylarkSemantics() default false;
}