1 /*******************************************************************************
2 * Copyright (c) 2000, 2011 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.corext.refactoring.code;
13 import org.eclipse.core.runtime.Assert;
15 import org.eclipse.jdt.core.dom.ASTVisitor;
16 import org.eclipse.jdt.core.dom.FieldAccess;
17 import org.eclipse.jdt.core.dom.IBinding;
18 import org.eclipse.jdt.core.dom.IMethodBinding;
19 import org.eclipse.jdt.core.dom.ITypeBinding;
20 import org.eclipse.jdt.core.dom.IVariableBinding;
21 import org.eclipse.jdt.core.dom.MethodInvocation;
22 import org.eclipse.jdt.core.dom.Modifier;
23 import org.eclipse.jdt.core.dom.Name;
24 import org.eclipse.jdt.core.dom.QualifiedName;
25 import org.eclipse.jdt.core.dom.SimpleName;
26 import org.eclipse.jdt.core.dom.SuperFieldAccess;
27 import org.eclipse.jdt.core.dom.SuperMethodInvocation;
28 import org.eclipse.jdt.core.dom.ThisExpression;
30 import org.eclipse.jdt.internal.corext.dom.fragments.ASTFragmentFactory;
31 import org.eclipse.jdt.internal.corext.dom.fragments.IExpressionFragment;
33 class ConstantChecks {
34 private static abstract class ExpressionChecker extends ASTVisitor {
36 private final IExpressionFragment fExpression;
37 protected boolean fResult= true;
39 public ExpressionChecker(IExpressionFragment ex) {
42 public boolean check() {
44 fExpression.getAssociatedNode().accept(this);
49 private static class LoadTimeConstantChecker extends ExpressionChecker {
50 public LoadTimeConstantChecker(IExpressionFragment ex) {
55 public boolean visit(SuperFieldAccess node) {
60 public boolean visit(SuperMethodInvocation node) {
65 public boolean visit(ThisExpression node) {
70 public boolean visit(FieldAccess node) {
71 fResult&= new LoadTimeConstantChecker((IExpressionFragment) ASTFragmentFactory.createFragmentForFullSubtree(node.getExpression())).check();
75 public boolean visit(MethodInvocation node) {
76 if(node.getExpression() == null) {
77 visitName(node.getName());
79 fResult&= new LoadTimeConstantChecker((IExpressionFragment) ASTFragmentFactory.createFragmentForFullSubtree(node.getExpression())).check();
85 public boolean visit(QualifiedName node) {
86 return visitName(node);
89 public boolean visit(SimpleName node) {
90 return visitName(node);
93 private boolean visitName(Name name) {
94 fResult&= checkName(name);
95 return false; //Do not descend further
98 private boolean checkName(Name name) {
99 IBinding binding= name.resolveBinding();
101 return true; /* If the binding is null because of compile errors etc.,
102 scenarios which may have been deemed unacceptable in
103 the presence of semantic information will be admitted. */
105 // If name represents a member:
106 if (binding instanceof IVariableBinding || binding instanceof IMethodBinding)
107 return isMemberReferenceValidInClassInitialization(name);
108 else if (binding instanceof ITypeBinding)
109 return ! ((ITypeBinding) binding).isTypeVariable();
111 /* IPackageBinding is not expected, as a package name not
112 used as a type name prefix is not expected in such an
113 expression. Other types are not expected either.
115 Assert.isTrue(false);
120 private boolean isMemberReferenceValidInClassInitialization(Name name) {
121 IBinding binding= name.resolveBinding();
122 Assert.isTrue(binding instanceof IVariableBinding || binding instanceof IMethodBinding);
124 if(name instanceof SimpleName)
125 return Modifier.isStatic(binding.getModifiers());
127 Assert.isTrue(name instanceof QualifiedName);
128 return checkName(((QualifiedName) name).getQualifier());
133 private static class StaticFinalConstantChecker extends ExpressionChecker {
134 public StaticFinalConstantChecker(IExpressionFragment ex) {
139 public boolean visit(SuperFieldAccess node) {
144 public boolean visit(SuperMethodInvocation node) {
149 public boolean visit(ThisExpression node) {
155 public boolean visit(QualifiedName node) {
156 return visitName(node);
159 public boolean visit(SimpleName node) {
160 return visitName(node);
162 private boolean visitName(Name name) {
163 IBinding binding= name.resolveBinding();
164 if(binding == null) {
165 /* If the binding is null because of compile errors etc.,
166 scenarios which may have been deemed unacceptable in
167 the presence of semantic information will be admitted.
173 int modifiers= binding.getModifiers();
174 if(binding instanceof IVariableBinding) {
175 if (!(Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers))) {
179 } else if(binding instanceof IMethodBinding) {
180 if (!Modifier.isStatic(modifiers)) {
184 } else if(binding instanceof ITypeBinding) {
185 return false; // It's o.k. Don't descend deeper.
188 /* IPackageBinding is not expected, as a package name not
189 used as a type name prefix is not expected in such an
190 expression. Other types are not expected either.
192 Assert.isTrue(false);
201 public static boolean isStaticFinalConstant(IExpressionFragment ex) {
202 return new StaticFinalConstantChecker(ex).check();
205 public static boolean isLoadTimeConstant(IExpressionFragment ex) {
206 return new LoadTimeConstantChecker(ex).check();