package sharpen.xobotos.generator; import static sharpen.core.framework.Environments.my; import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.ConstructorInvocation; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.SuperConstructorInvocation; import sharpen.core.CSharpBuilder; import sharpen.core.Sharpen; import sharpen.core.csharp.ast.*; import sharpen.core.framework.BindingUtils; import sharpen.core.framework.CSharpDriver.IBuilderDelegate; import sharpen.core.framework.CSharpDriver.IMethodBuilderDelegate; import sharpen.xobotos.api.bindings.BindingManager; import sharpen.xobotos.api.templates.MemberTemplate; import sharpen.xobotos.output.OutputMode; import sharpen.xobotos.output.OutputType; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.List; public abstract class AbstractMethodBuilder<T extends CSMethodBase, U extends MemberTemplate<MethodDeclaration, T>> extends MemberBuilder<MethodDeclaration, T, U> { private List<IMethodBinding> _invocationTargets; public AbstractMethodBuilder(U template, Class<T> memberType, OutputType output, MethodDeclaration node) { super(template, memberType, output, node); } public boolean isConstructor() { return getASTNode().isConstructor(); } @Override public String getNodeName() { return BindingUtils.qualifiedSignature(getASTNode().resolveBinding()); } @Override protected boolean buildInternal(CSharpBuilder builder, IBuilderDelegate<?> dlg, T method) { IMethodBuilderDelegate delegate = (IMethodBuilderDelegate) dlg; if (!isConstructor() && (getOutputMode() == OutputMode.ABSTRACT_STUB)) { ((CSMethod) method).modifier(CSMethodModifier.Abstract); method.addAttribute(new CSAttribute("Sharpen.Stub")); method.setStub(); return true; } if (Modifier.isNative(getASTNode().getModifiers())) { stubBlock(method.body()); method.setStub(); if (getOutputMode() == OutputMode.STUB) method.addAttribute(new CSAttribute("Sharpen.Stub")); else method.addAttribute(new CSAttribute("Sharpen.NativeStub")); return true; } if (getOutputMode() == OutputMode.SHARPEN) { delegate.mapBody(method); return true; } if (isConstructor() && !getOutputType().removeChainedConstructorInvocations()) mapChainedConstructors(builder, (CSConstructor) method); stubBlock(method.body()); method.setStub(); method.addAttribute(new CSAttribute("Sharpen.Stub")); return true; } private void mapChainedConstructors(final CSharpBuilder builder, final CSConstructor ctor) { getASTNode().accept(new ASTVisitor() { @Override public boolean visit(ConstructorInvocation node) { addChainedConstructorInvocation(new CSThisExpression(), node.arguments(), node.resolveConstructorBinding()); return false; } @Override public boolean visit(SuperConstructorInvocation node) { addChainedConstructorInvocation(new CSBaseExpression(), node.arguments(), node.resolveConstructorBinding()); return false; } private void addChainedConstructorInvocation(CSExpression target, List<?> args, IMethodBinding binding) { CSConstructorInvocationExpression cie = builder.mapChainedConstructorInvocation(target, args, binding); ctor.chainedConstructorInvocation(cie); } }); } protected void checkInvocationTarget(IMethodBinding binding) { if (!BindingManager.reportStubUsage()) return; final IMethodBinding current = getASTNode().resolveBinding(); final BindingManager.MethodEntry entry = my(BindingManager.class).lookupMethod(binding); if ((entry == null) || (entry.Output == null)) { Sharpen.Debug("[%s]: Cannot lookup target method for invocation '%s'", BindingUtils.qualifiedSignature(current), BindingUtils.qualifiedSignature(binding)); return; } if (getOutputMode() != OutputMode.SHARPEN) return; if (entry.Output.getMode() == OutputMode.SHARPEN) return; if (_invocationTargets == null) _invocationTargets = new ArrayList<IMethodBinding>(); if (_invocationTargets.contains(binding)) return; Sharpen.Debug("[%s]: Invoking non-sharpened method '%s'", BindingUtils.qualifiedSignature(current), BindingUtils.qualifiedSignature(binding)); CSAttribute attr = new CSAttribute("Sharpen.UsesStub"); String escaped = "@\"" + BindingUtils.qualifiedSignature(binding) + "\""; attr.addArgument(new CSStringLiteralExpression(escaped)); getMember().addAttribute(attr); _invocationTargets.add(binding); } }