1 /*
  2  * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package jdk.incubator.code;
 27 
 28 import java.lang.annotation.*;
 29 import java.lang.reflect.Method;
 30 
 31 /**
 32  * An annotation that is used to declare reflectable methods, lambda expressions, and method references. Declaration
 33  * of such reflectable program elements enables access to their code as a code model.
 34  * <p>
 35  * The code model of a reflectable method is accessed by invoking {@link Op#ofMethod(Method)} with an argument
 36  * that is a {@link Method} instance (retrieved using core reflection) representing the reflectable method. The result
 37  * is an optional value that contains a root operation modeling the method. For example,
 38  * {@snippet lang = java:
 39  *    static class MyClass {
 40  *        @Reflect
 41  *        void reflectableMethod(int i) { IO.println(i); }
 42  *    }
 43  *
 44  *    Method m = MyClass.class.getDeclaredMethod("reflectableMethod", int.class);
 45  *    CoreOp.FuncOp codeModel = Op.ofMethod(m).orElseThrow();
 46  * }
 47  * <p>
 48  * The code model of a reflectable lambda expression (or method reference) is accessed by invoking
 49  * {@link Op#ofLambda(Object)} with an argument that is an instance of a functional interface associated with the
 50  * reflectable lambda expression. The result is an optional value that contains a {@link Quoted quoted} instance, from
 51  * which may be retrieved the operation modeling the lambda expression. In addition, it is possible to retrieve
 52  * a mapping from {@link Value values} in the code model that model final, or effectively final, variables used but not
 53  * declared in the lambda expression to their corresponding run time values. Such run time values are commonly referred
 54  * to as captured values. For example:
 55  * {@snippet lang = java:
 56  *    int capture = 42;
 57  *    @Reflect
 58  *    IntConsumer reflectableLambda = i -> { IO.println(i + capture); };
 59  *
 60  *    Quoted<JavaOp.LambdaOp> quotedCodeModel = Op.ofLambda(reflectableLambda)
 61  *        .orElseThrow();
 62  *    JavaOp.LambdaOp codeModel = quotedCodeModel.op();
 63  *
 64  *    SequencedMap<Value, Object> capturedValues = quotedCodeModel.capturedValues();
 65  *    assert capturedValues.size() == 1;
 66  *    assert capturedValues.values().contains(42);
 67  * }
 68  * <p>
 69  * There are four syntactic locations where {@code @Reflect} can appear, forming three cases in increasing scope of what
 70  * is declared reflectable.
 71  * <ol>
 72  * <li>
 73  * If the annotation appears in a cast expression of a lambda expression (or method reference), annotating the use of
 74  * the type in the cast operator of the cast expression, then the lambda expression is declared reflectable. For
 75  * example,
 76  * {@snippet lang=java :
 77  *    method((@Reflect IntConsumer) i -> { ... });
 78  * }
 79  * </li>
 80  * <li>
 81  * If the annotation appears as a modifier for a field declaration or a local variable declaration, annotating the
 82  * field or local variable, then any lambda expressions (or method references) in the variable initializer expression
 83  * (if present) are declared reflectable. This is useful when cast expressions become verbose and/or types become hard
 84  * to reason about, such as with fluent stream-like expressions where many reflectable lambda expressions are
 85  * passed as arguments. For example,
 86  * {@snippet lang=java :
 87  *    @Reflect
 88  *    IntConsumer reflectableLambda = i -> { ... };
 89  *    method(reflectableLambda);
 90  * }
 91  * </li>
 92  * <li>
 93  * Finally, if the annotation appears as a modifier for a non-abstract method declaration, annotating the method, then
 94  * the method and any lambda expressions (or method references) it contains are declared reflectable. For example,
 95  * {@snippet lang=java :
 96  *    @Reflect
 97  *    void reflectableMethod(int i) { ... }
 98  * }
 99  * </li>
100  * </ol>
101  * If a method or lambda expression (or method reference) is declared reflectable then the compiler generates an error
102  * message if it contains program elements that cannot be modeled (and therefore a code model cannot be produced).
103  * <p>
104  * The annotation is ignored if it appears in any other valid syntactic location.
105  * <p>
106  * Declaring a reflectable lambda expression or method does not implicitly broaden the scope of what is reflectable to
107  * methods they invoke. Furthermore, declaring a reflectable lambda expression does broaden the scope to the surrounding
108  * code of final, or effectively final, variables used but not declared in the lambda expression.
109  * Declaring a reflectable method reference does not implicitly broaden the scope to the referenced method.
110  * A reflectable method reference's code model is the same as the code model of an equivalent reflectable lambda
111  * expression whose body invokes the referenced method.
112  *
113  * @see Op#ofMethod(Method)
114  * @see Op#ofLambda(Object)
115  */
116 @Target({ElementType.LOCAL_VARIABLE, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE_USE})
117 @Retention(RetentionPolicy.RUNTIME)
118 public @interface Reflect {
119 }