|
125 | 125 | * out, but new language features are then implicitly also available and this may not be desirable. |
126 | 126 | * The implication is that you might need to update your configuration with each new release. |
127 | 127 | * <p> |
| 128 | + * The statement and expression lists are matched by exact class, so naming a class does not name its |
| 129 | + * subclasses. Several language constructs are modelled as a subclass of another: a lambda is a |
| 130 | + * {@link org.codehaus.groovy.ast.expr.LambdaExpression}, which extends |
| 131 | + * {@link org.codehaus.groovy.ast.expr.ClosureExpression}; the {@code ::} form of a method reference is |
| 132 | + * a {@link org.codehaus.groovy.ast.expr.MethodReferenceExpression}, which extends |
| 133 | + * {@link org.codehaus.groovy.ast.expr.MethodPointerExpression}; and attribute access is an |
| 134 | + * {@link org.codehaus.groovy.ast.expr.AttributeExpression}, which extends |
| 135 | + * {@link org.codehaus.groovy.ast.expr.PropertyExpression}. Each has to be listed in its own right. |
| 136 | + * This is another reason to prefer allowed lists, which refuse an unlisted subclass rather than |
| 137 | + * admitting one. |
| 138 | + * <p> |
128 | 139 | * If neither an allowed list nor a disallowed list is set, then everything is permitted. |
129 | 140 | * <p> |
130 | 141 | * Combinations of import and star import constraints are authorized as long as you use the same type of list for both. |
|
220 | 231 | * {@link #setIndirectImportCheckEnabled(boolean)} flag exists to catch some of those, but only |
221 | 232 | * within the code this customizer visits. |
222 | 233 | * <p> |
| 234 | + * Where this customizer sits in the compilation explains both of the limitations above and one |
| 235 | + * more. It runs at {@link org.codehaus.groovy.control.CompilePhase#CANONICALIZATION}, which is after |
| 236 | + * the phases in which annotations that execute have already done so, and before the phase in which |
| 237 | + * types are inferred. So the type this customizer sees for an expression is the type the source |
| 238 | + * states, and for anything left to the runtime that is {@code java.lang.Object}: in |
| 239 | + * {@code def r = java.lang.Runtime; r.getRuntime()} the receiver of the call is {@code Object}, not |
| 240 | + * {@code Runtime}, and a receiver list naming {@code Runtime} does not match it. Compiling statically |
| 241 | + * does not change this, since {@code @CompileStatic} and {@code @TypeChecked} run at |
| 242 | + * {@link org.codehaus.groovy.control.CompilePhase#INSTRUCTION_SELECTION}, three phases later. |
| 243 | + * <p> |
223 | 244 | * More fundamentally, <i>compiling</i> Groovy source is itself code execution, whether or not you |
224 | 245 | * subsequently run the result: global AST transforms found on the compile classpath, |
225 | 246 | * {@code @groovy.transform.ASTTest}, {@code @Grab} dependency resolution and static initializers all |
|
0 commit comments