/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.wst.jsdt.internal.corext.refactoring.delegates; import java.util.List; import org.eclipse.core.runtime.Assert; import org.eclipse.wst.jsdt.core.JavaScriptModelException; import org.eclipse.wst.jsdt.core.dom.ASTNode; import org.eclipse.wst.jsdt.core.dom.Block; import org.eclipse.wst.jsdt.core.dom.BodyDeclaration; import org.eclipse.wst.jsdt.core.dom.ChildPropertyDescriptor; import org.eclipse.wst.jsdt.core.dom.ConstructorInvocation; import org.eclipse.wst.jsdt.core.dom.ExpressionStatement; import org.eclipse.wst.jsdt.core.dom.IBinding; import org.eclipse.wst.jsdt.core.dom.FunctionDeclaration; import org.eclipse.wst.jsdt.core.dom.FunctionInvocation; import org.eclipse.wst.jsdt.core.dom.FunctionRef; import org.eclipse.wst.jsdt.core.dom.FunctionRefParameter; import org.eclipse.wst.jsdt.core.dom.PrimitiveType; import org.eclipse.wst.jsdt.core.dom.ReturnStatement; import org.eclipse.wst.jsdt.core.dom.SimpleName; import org.eclipse.wst.jsdt.core.dom.SingleVariableDeclaration; import org.eclipse.wst.jsdt.core.dom.Statement; import org.eclipse.wst.jsdt.core.dom.Type; import org.eclipse.wst.jsdt.internal.corext.dom.ASTNodeFactory; import org.eclipse.wst.jsdt.internal.corext.refactoring.RefactoringCoreMessages; /** * Delegate creator for static and non-static methods. * * */ public class DelegateMethodCreator extends DelegateCreator { private ASTNode fDelegateInvocation; private FunctionRef fDocMethodReference; protected void initialize() { Assert.isTrue(getDeclaration() instanceof FunctionDeclaration); if (getNewElementName() == null) setNewElementName(((FunctionDeclaration) getDeclaration()).getName().getIdentifier()); setInsertBefore(true); } protected ASTNode createBody(BodyDeclaration bd) throws JavaScriptModelException { FunctionDeclaration methodDeclaration= (FunctionDeclaration) bd; // interface or abstract method ? => don't create a method body. if (methodDeclaration.getBody() == null) return null; return createDelegateMethodBody(methodDeclaration); } protected ASTNode createDocReference(final BodyDeclaration declaration) throws JavaScriptModelException { fDocMethodReference= getAst().newFunctionRef(); fDocMethodReference.setName(getAst().newSimpleName(getNewElementName())); if (isMoveToAnotherFile()) fDocMethodReference.setQualifier(createDestinationTypeName()); createArguments((FunctionDeclaration) declaration, fDocMethodReference.parameters(), false); return fDocMethodReference; } protected ASTNode getBodyHead(BodyDeclaration result) { return result; } protected ChildPropertyDescriptor getJavaDocProperty() { return FunctionDeclaration.JAVADOC_PROPERTY; } protected ChildPropertyDescriptor getBodyProperty() { return FunctionDeclaration.BODY_PROPERTY; } /** * @return the delegate incovation, either a {@link ConstructorInvocation} * or a {@link FunctionInvocation}. May be null if the delegate * method is abstract (and therefore has no body at all) */ public ASTNode getDelegateInvocation() { return fDelegateInvocation; } /** * @return the javadoc reference to the old method in the javadoc comment. * May be null if no comment was created. */ public FunctionRef getJavadocReference() { return fDocMethodReference; } /** * Creates the corresponding statement for the method invocation, based on * the return type. * * @param declaration the method declaration where the invocation statement * is inserted * @param invocation the method invocation being encapsulated by the * resulting statement * @return the corresponding statement */ protected Statement createMethodInvocation(final FunctionDeclaration declaration, final FunctionInvocation invocation) { Assert.isNotNull(declaration); Assert.isNotNull(invocation); Statement statement= null; final Type type= declaration.getReturnType2(); if (type == null) statement= createExpressionStatement(invocation); else { if (type instanceof PrimitiveType) { final PrimitiveType primitive= (PrimitiveType) type; if (primitive.getPrimitiveTypeCode().equals(PrimitiveType.VOID)) statement= createExpressionStatement(invocation); else statement= createReturnStatement(invocation); } else statement= createReturnStatement(invocation); } return statement; } /** * {@inheritDoc} */ protected IBinding getDeclarationBinding() { final FunctionDeclaration declaration= (FunctionDeclaration) getDeclaration(); return declaration.resolveBinding(); } private void createArguments(final FunctionDeclaration declaration, final List arguments, boolean methodInvocation) throws JavaScriptModelException { Assert.isNotNull(declaration); Assert.isNotNull(arguments); SingleVariableDeclaration variable= null; final int size= declaration.parameters().size(); for (int index= 0; index < size; index++) { variable= (SingleVariableDeclaration) declaration.parameters().get(index); if (methodInvocation) { // we are creating method invocation parameters final SimpleName expression= getAst().newSimpleName(variable.getName().getIdentifier()); arguments.add(expression); } else { // we are creating type info for the javadoc final FunctionRefParameter parameter= getAst().newFunctionRefParameter(); parameter.setType(ASTNodeFactory.newType(getAst(), variable)); if ((index == size - 1) && declaration.isVarargs()) parameter.setVarargs(true); arguments.add(parameter); } } } private Block createDelegateMethodBody(final FunctionDeclaration declaration) throws JavaScriptModelException { Assert.isNotNull(declaration); FunctionDeclaration old= (FunctionDeclaration) getDeclaration(); List arguments; Statement call; if (old.isConstructor()) { ConstructorInvocation invocation= getAst().newConstructorInvocation(); arguments= invocation.arguments(); call= invocation; fDelegateInvocation= invocation; } else { FunctionInvocation invocation= getAst().newFunctionInvocation(); invocation.setName(getAst().newSimpleName(getNewElementName())); invocation.setExpression(getAccess()); arguments= invocation.arguments(); call= createMethodInvocation(declaration, invocation); fDelegateInvocation= invocation; } createArguments(declaration, arguments, true); final Block body= getAst().newBlock(); body.statements().add(call); return body; } /** * Creates a new expression statement for the method invocation. * * @param invocation the method invocation * @return the corresponding statement */ private ExpressionStatement createExpressionStatement(final FunctionInvocation invocation) { Assert.isNotNull(invocation); return invocation.getAST().newExpressionStatement(invocation); } /** * Creates a new return statement for the method invocation. * * @param invocation the method invocation to create a return statement for * @return the corresponding statement */ private ReturnStatement createReturnStatement(final FunctionInvocation invocation) { Assert.isNotNull(invocation); final ReturnStatement statement= invocation.getAST().newReturnStatement(); statement.setExpression(invocation); return statement; } protected String getTextEditGroupLabel() { return RefactoringCoreMessages.DelegateMethodCreator_text_edit_group_field; } }