Community
Participate
Working Groups
Need to be able to retrieve the compile-time constant from expression in the dom ast. This is necessary while examining the member values of annotations. Proposed API which will behave very similarly to org.eclipse.jdt.core.dom.IVariableBinding.getConstantValue() /** * Return the compile-time constant of the expression if one exists. * * Primitive types are wrapped in their boxed equivalen * Strings are simply returned as strings. * Return null for enum constants or if the expression does not evaluate to a compile-time constant. * */ Object org.eclipse.jdt.core.dom.Expression.getContantValue()
Olivier - pls consider for M6.
Created attachment 19066 [details] Apply on org.eclipse.jdt.core.dom package in HEAD Proposal. This adds the getConstant() method on org.eclipse.jdt.core.dom.Expression class. It also adds the corresponding PROPERTY for each subclass that might have a constant value.
Created attachment 19067 [details] Apply on org.eclipse.jdt.core.dom package in HEAD New patch. The previous patch had some bugs with the CONSTANT properties.
I need to find out if the constant should be propagated when a node is cloned.
Created attachment 19068 [details] Apply on org.eclipse.jdt.core.dom package in HEAD New version that propagates the constant during cloning operation. I also added the constant for PostfixExpression. I missed it.
Jim, Could you please review the last patch for M6? Let me know if anything is wrong.
The patch adds a new structural property to certain AST nodes. Since the structure of the AST nodes is dictated by the grammar, which hasn't changed, there's something suspicious about your whole approach. This problem report is closely related to bug 79112.
Created attachment 19078 [details] Apply on org.eclipse.jdt.core.dom package in HEAD I removed the properties for all the nodes, but I preserved the getConstant() API.
(1) Computing a compile-time for Java requires bindings to handle the full generality of what the compiler does: "OtherClass.FOO + 1" is compile-time computable if OtherClass.FOO resolves to a public static final field which itself has a compile-time-computable value. If there are no bindings, there as some compile-time computable expression for which it will be impossible to compute a value. (2) Computing a compile-time value should be easily doable with a simple ASTVisitor. Have you tried that? If that works, there would be no pressing need to add new API. Theodora: please comment on what your needs
If the DOM/AST is built without bindings, it is perfectly acceptable to return null or throw exceptions for Expression.getConstantValue() on all expressions. In my use case, the AST nodes are as valuable as the bindings that the nodes generated and having one without the other is of no use. Does that answer your question? May I ask, what exactly are the problems that the jdt is faced with in providing the requested API? It is possible to write a constant expression evaluator using the ASTVisitor and IVaribleBinding.getConstantValue() API. However, one would argue that this exact piece of code already exists in the java compiler. In fact, it is possibly the same piece of code that handles IVariableBinding.getConstantValue ().
The use case is to be able to get the constant value for JSR-175 annotation member values. I agree that constant values should not be present if bindings aren't present. We could write our own constant expression evaluator, but it's not trivial. In our own compiler the evaluator is 1000 lines of code to deal with all the edge cases of overflow, underflow, type promotion, divide by zero, string escape processing, etc. It seems silly to replicate so much logic that is already present in the JDT.
Theodora and Tim, Thanks for your quick feedback. I like to make sure that any API we do add is solving a real problem and that we can sustain it going forward. Here's a slightly revised and renamed spec for a method on Expression: /** * Resolves and returns the compile-time constant expression value as * specified in JLS2 15.28, if this expression has one. Constant expression * values are unavailable unless bindings are requested when the AST is * being built. If the type of the value is a primitive type, the result * is the boxed equivalent (i.e., int returned as an <code>Integer</code>); * if the type of the value is <code>String</code>, the result is the string * itself. If the expression does not have a compile-time constant expression * value, the result is <code>null</code>. * <p> * Resolving constant expressions takes into account the value of simple * and qualified names that refer to constant variables (JLS2 4.12.4). * </p> * <p> * Note 1: enum constants are not considered constant expressions either. * The result is always <code>null</code> for these. * </p> * <p> * Note 2: Compile-time constant expressions cannot denote <code>null</code>. * So technically {@link NullLiteral} nodes are not constant expressions. * The result is <code>null</code> for these nonetheless. * </p> * * @return the constant expression value, or <code>null</code> if this * expression has no constant expression value or if bindings were not * requested when the AST was created * @since 3.1 */ public final Object resolveConstantExpressionValue() { return internalResolveConstantExpressionValue(); } Let us know whether this will do the trick. Olivier, Is there a way to implement this that does not involve adding 4 bytes to most every Expression node subtype and especially Names? (If you can't find a better way, you should go ahead and add the internal constant field on Expression itself since it won't really make it much bigger in practice.) Also, clone() does not copy bindings; it should not copy the constant either.
This API will exactly meet our needs. Thank you.
I could do it lazily using the binding resolver. This would not add any instance variable for the node and we keep the code local to the Expression class.
+1 - Funneling everything through the binding resolver is the way to go.
Down the road, some caching in a separate map could occur (node->constant) if sharing was an issue.
Fixed and released in HEAD. Regression tests added in existing tests.
See ASTConverter15Test.test0151/0152.
Verified in 20050330-0500
Closing all completed bugs reports