/* Copyright (C) 2004 - 2008 Versant Inc. http://www.db4o.com
This file is part of the sharpen open source java to c# translator.
sharpen is free software; you can redistribute it and/or modify it under
the terms of version 2 of the GNU General Public License as published
by the Free Software Foundation and as clarified by db4objects' GPL
interpretation policy, available at
http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
Suite 350, San Mateo, CA 94403, USA.
sharpen is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Copyright (C) 2006 Versant Inc. http://www.db4o.com */
package sharpen.core;
import sharpen.core.csharp.ast.*;
import org.eclipse.jdt.core.dom.*;
/**
* @exclude
*/
public abstract class AbstractNestedClassBuilder extends CSharpBuilder {
private boolean _usesEnclosingMember;
public AbstractNestedClassBuilder(CSharpBuilder other) {
super(other);
}
protected abstract ITypeBinding nestedTypeBinding();
@Override
protected CSExpression mapMethodTargetExpression(MethodInvocation node) {
if (null == node.getExpression()) {
return createEnclosingTargetReferences(node.getName());
}
return super.mapMethodTargetExpression(node);
}
public boolean visit(ThisExpression node) {
if (null == node.getQualifier()) return super.visit(node);
pushExpression(createEnclosingThisReference(node.getQualifier().resolveTypeBinding(), true));
return false;
}
public boolean visit(SimpleName name) {
if (isInstanceFieldReference(name)) {
pushExpression(createEnclosingReferences(name));
return false;
}
return super.visit(name);
}
private boolean isInstanceFieldReference(SimpleName name) {
IBinding binding = name.resolveBinding();
if (IBinding.VARIABLE != binding.getKind()) return false;
return ((IVariableBinding)binding).isField();
}
private CSExpression createEnclosingReferences(SimpleName name) {
CSExpression target = createEnclosingTargetReferences(name);
return new CSMemberReferenceExpression(target, mappedName(name));
}
private CSExpression createEnclosingTargetReferences(SimpleName name) {
ITypeBinding enclosingClassBinding = getDeclaringClass(name);
CSExpression target = isStaticMember(name)
? createTypeReference(enclosingClassBinding)
: createEnclosingThisReference(enclosingClassBinding);
return target;
}
private CSExpression createEnclosingThisReference(ITypeBinding enclosingClassBinding) {
return createEnclosingThisReference(enclosingClassBinding, false);
}
private CSExpression createEnclosingThisReference(
ITypeBinding enclosingClassBinding, boolean ignoreSuperclass) {
CSExpression enclosing = new CSThisExpression();
ITypeBinding binding = nestedTypeBinding();
ITypeBinding to = enclosingClassBinding;
while (binding != to && (ignoreSuperclass || !isSuperclass(binding, to))) {
requireEnclosingReference();
enclosing = new CSMemberReferenceExpression(enclosing, "_enclosing");
binding = binding.getDeclaringClass();
if (null == binding) break;
}
return enclosing;
}
protected boolean isEnclosingReferenceRequired() {
return _usesEnclosingMember;
}
protected void requireEnclosingReference() {
_usesEnclosingMember = true;
}
private String mappedName(SimpleName name) {
IBinding binding = name.resolveBinding();
return binding instanceof IMethodBinding ? mappedMethodName((IMethodBinding) binding) : identifier(name);
}
private boolean isStaticMember(SimpleName name) {
return Modifier.isStatic(name.resolveBinding().getModifiers());
}
private boolean isSuperclass(ITypeBinding type, ITypeBinding candidate) {
ITypeBinding superClass = type.getSuperclass();
while (null != superClass) {
if (superClass == candidate) {
return true;
}
superClass = superClass.getSuperclass();
}
return false;
}
private ITypeBinding getDeclaringClass(Name reference) {
IBinding binding = reference.resolveBinding();
switch (binding.getKind()) {
case IBinding.METHOD: {
return ((IMethodBinding)binding).getDeclaringClass();
}
case IBinding.VARIABLE: {
IVariableBinding variable = (IVariableBinding)binding;
return variable.getDeclaringClass();
}
}
//throw new UnsupportedOperationException();
return null;
}
protected CSField createEnclosingField() {
return CSharpCode.newPrivateReadonlyField("_enclosing", enclosingTypeReference());
}
private CSTypeReference enclosingTypeReference() {
return new CSTypeReference(_currentType.name());
}
protected CSInfixExpression createFieldAssignment(String fieldName, String rvalue) {
return createFieldAssignment(fieldName, new CSReferenceExpression(rvalue));
}
protected CSInfixExpression createFieldAssignment(String fieldName,
final CSExpression fieldValue) {
CSExpression fieldReference = new CSMemberReferenceExpression(new CSThisExpression(), fieldName);
return new CSInfixExpression("=", fieldReference, fieldValue);
}
}