Bug 88548 - Need to get constant value on expression
Summary: Need to get constant value on expression
Status: CLOSED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.1   Edit
Hardware: PC Windows XP
: P3 enhancement (vote)
Target Milestone: 3.1 M6   Edit
Assignee: Olivier Thomann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-03-18 19:19 EST by Theodora Yeung CLA
Modified: 2005-10-20 18:22 EDT (History)
1 user (show)

See Also:


Attachments
Apply on org.eclipse.jdt.core.dom package in HEAD (38.93 KB, patch)
2005-03-21 15:54 EST, Olivier Thomann CLA
no flags Details | Diff
Apply on org.eclipse.jdt.core.dom package in HEAD (39.89 KB, patch)
2005-03-21 16:18 EST, Olivier Thomann CLA
no flags Details | Diff
Apply on org.eclipse.jdt.core.dom package in HEAD (44.82 KB, patch)
2005-03-21 16:32 EST, Olivier Thomann CLA
no flags Details | Diff
Apply on org.eclipse.jdt.core.dom package in HEAD (29.79 KB, patch)
2005-03-22 10:12 EST, Olivier Thomann CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Theodora Yeung CLA 2005-03-18 19:19:28 EST
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()
Comment 1 Philipe Mulet CLA 2005-03-19 02:33:45 EST
Olivier - pls consider for M6.
Comment 2 Olivier Thomann CLA 2005-03-21 15:54:54 EST
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.
Comment 3 Olivier Thomann CLA 2005-03-21 16:18:41 EST
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.
Comment 4 Olivier Thomann CLA 2005-03-21 16:23:44 EST
I need to find out if the constant should be propagated when a node is cloned.
Comment 5 Olivier Thomann CLA 2005-03-21 16:32:05 EST
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.
Comment 6 Olivier Thomann CLA 2005-03-21 16:32:48 EST
Jim,

Could you please review the last patch for M6? Let me know if anything is wrong.
Comment 7 Jim des Rivieres CLA 2005-03-21 19:26:51 EST
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.
Comment 8 Olivier Thomann CLA 2005-03-22 10:12:09 EST
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.
Comment 9 Jim des Rivieres CLA 2005-03-22 12:32:46 EST
(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

Comment 10 Theodora Yeung CLA 2005-03-22 18:55:46 EST
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
(). 

Comment 11 Tim Hanson CLA 2005-03-22 19:12:16 EST
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.
Comment 12 Jim des Rivieres CLA 2005-03-22 20:46:12 EST
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.

Comment 13 Tim Hanson CLA 2005-03-22 21:10:27 EST
This API will exactly meet our needs. Thank you.
Comment 14 Olivier Thomann CLA 2005-03-23 14:29:52 EST
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.
Comment 15 Jim des Rivieres CLA 2005-03-23 14:57:33 EST
+1 - Funneling everything through the binding resolver is the way to go.
Comment 16 Philipe Mulet CLA 2005-03-23 15:42:06 EST
Down the road, some caching in a separate map could occur (node->constant) if
sharing was an issue.
Comment 17 Olivier Thomann CLA 2005-03-23 16:14:50 EST
Fixed and released in HEAD.
Regression tests added in existing tests.
Comment 18 Olivier Thomann CLA 2005-03-23 16:16:16 EST
See ASTConverter15Test.test0151/0152.
Comment 19 Olivier Thomann CLA 2005-03-30 23:33:02 EST
Verified in 20050330-0500
Comment 20 Theodora Yeung CLA 2005-10-20 18:22:48 EDT
Closing all completed bugs reports