blob: 12adc310b38af6e494cea3132666873ff47a9f01 [file] [log] [blame]
/**********************************************************************
* This file is part of "Object Teams Development Tooling"-Software
*
* Copyright 2010 Stephan Herrmann.
*
* 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
* $Id$
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
* Contributors:
* Stephan Herrmann - Initial API and implementation
**********************************************************************/
package org.eclipse.objectteams.otdt.internal.ui.util;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.CallinMappingDeclaration;
import org.eclipse.jdt.core.dom.CalloutMappingDeclaration;
import org.eclipse.jdt.core.dom.FieldAccessSpec;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.MethodBindingOperator;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodSpec;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
import org.eclipse.jdt.core.dom.PrimitiveType;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings;
import org.eclipse.jdt.internal.core.manipulation.StubUtility;
import org.eclipse.jdt.core.manipulation.CodeGeneration;
import base org.eclipse.jdt.internal.corext.codemanipulation.StubUtility2;
/**
* OT-Extension for {@link org.eclipse.jdt.internal.corext.codemanipulation.StubUtility2}.
* @since 0.7.0 (previously these methods resided in {@link org.eclipse.objectteams.otdt.internal.ui.assist.CompletionAdaptor.StubUtility2})
*/
@SuppressWarnings({"restriction", "rawtypes", "unchecked"})
public team class OTStubUtility {
private static OTStubUtility instance;
@SuppressWarnings("decapsulation")
protected class StubUtility2 playedBy StubUtility2 {
protected List createParameters(IJavaProject project, ImportRewrite imports,
ImportRewriteContext context, AST ast, IMethodBinding binding,
String[] paramNames, MethodDeclaration decl)
->
List createParameters(IJavaProject project, ImportRewrite imports,
ImportRewriteContext context, AST ast, IMethodBinding binding,
String[] paramNames, MethodDeclaration decl);
}
static OTStubUtility getDefault() {
if (instance == null)
instance = new OTStubUtility();
return instance;
}
List createParameters(IJavaProject project, ImportRewrite imports,
ImportRewriteContext context, AST ast, IMethodBinding binding,
MethodDeclaration decl)
{
return StubUtility2.createParameters(project, imports, context, ast, binding, null/*use suggested argument names*/, decl);
}
/** This method is inspired by createImplementationStub(..), but much leaner. */
public static CalloutMappingDeclaration createCallout(ICompilationUnit unit,
ASTRewrite rewrite,
ImportRewrite imports,
IMethodBinding binding,
String type,
CodeGenerationSettings settings)
throws CoreException
{
AST ast= rewrite.getAST();
CalloutMappingDeclaration decl= ast.newCalloutMappingDeclaration();
decl.setSignatureFlag(true);
// no modifiers
MethodSpec spec = ast.newMethodSpec();
spec.setSignatureFlag(true);
spec.setName(ast.newSimpleName(binding.getName()));
// no type parameters
spec.setReturnType2(imports.addImport(binding.getReturnType(), ast));
// this helps to reuse some code regarding methods:
MethodDeclaration method = ast.newMethodDeclaration();
List parameters= getDefault().createParameters(unit.getJavaProject(), imports, null, ast, binding, method);
spec.parameters().addAll(ASTNode.copySubtrees(ast, parameters)); // copy to re-parent
decl.setRoleMappingElement(spec);
decl.setBaseMappingElement((MethodSpec)ASTNode.copySubtree(ast, spec));
// no thrown exceptions
String delimiter= StubUtility.getLineDelimiterUsed(unit);
// no body
if (settings.createComments) {
// TODO(SH): this reuses the template for overridden methods, should actually define our own template.
String string= CodeGeneration.getMethodComment(unit, type, method, binding, delimiter);
if (string != null) {
Javadoc javadoc= (Javadoc) rewrite.createStringPlaceholder(string, ASTNode.JAVADOC);
decl.setJavadoc(javadoc);
}
}
// no override annotation
return decl;
}
/** This method is inspired by createImplementationStub(..), but much leaner. */
public static CallinMappingDeclaration createCallin(ICompilationUnit unit,
ASTRewrite rewrite,
ImportRewrite imports,
IMethodBinding binding,
String type,
ModifierKeyword callinModifier,
CodeGenerationSettings settings)
throws CoreException
{
AST ast= rewrite.getAST();
CallinMappingDeclaration decl= ast.newCallinMappingDeclaration();
decl.setBindingOperator(ast.newMethodBindingOperator(callinModifier, MethodBindingOperator.KIND_CALLIN));
// no regular modifiers
MethodSpec spec = ast.newMethodSpec();
spec.setSignatureFlag(true);
spec.setName(ast.newSimpleName(binding.getName()));
// no type parameters
spec.setReturnType2(imports.addImport(binding.getReturnType(), ast));
// this helps to reuse some code regarding methods:
MethodDeclaration method = ast.newMethodDeclaration();
List parameters= getDefault().createParameters(unit.getJavaProject(), imports, null, ast, binding, method);
spec.parameters().addAll(ASTNode.copySubtrees(ast, parameters)); // copy to re-parent
decl.setRoleMappingElement(spec);
decl.getBaseMappingElements().add(ASTNode.copySubtree(ast, spec));
// no thrown exceptions
String delimiter= StubUtility.getLineDelimiterUsed(unit);
// no body
if (settings.createComments) {
// TODO(SH): this reuses the template for overridden methods, should actually define our own template.
String string= CodeGeneration.getMethodComment(unit, type, method, binding, delimiter);
if (string != null) {
Javadoc javadoc= (Javadoc) rewrite.createStringPlaceholder(string, ASTNode.JAVADOC);
decl.setJavadoc(javadoc);
}
}
// no override annotation
return decl;
}
/** Stripped down version of createCallout for use after '<-' : */
public static MethodSpec createMethodSpec(ICompilationUnit unit,
ASTRewrite rewrite,
ImportRewrite imports,
IMethodBinding binding,
boolean hasSignature)
throws CoreException
{
AST ast= rewrite.getAST();
MethodSpec spec = ast.newMethodSpec();
spec.setSignatureFlag(hasSignature);
spec.setName(ast.newSimpleName(binding.getName()));
// no type parameters
spec.setReturnType2(imports.addImport(binding.getReturnType(), ast));
// this helps to reuse some code regarding methods:
MethodDeclaration method = ast.newMethodDeclaration();
List parameters= getDefault().createParameters(unit.getJavaProject(), imports, null, ast, binding, method);
spec.parameters().addAll(ASTNode.copySubtrees(ast, parameters)); // copy to re-parent
return spec;
}
/** New factory method: */
public static CalloutMappingDeclaration createCalloutToField(ICompilationUnit unit,
ASTRewrite rewrite,
ImportRewrite imports,
String accessorName,
IVariableBinding field,
boolean isSetter,
String declaringType,
CodeGenerationSettings settings)
throws CoreException
{
AST ast= rewrite.getAST();
CalloutMappingDeclaration decl= ast.newCalloutMappingDeclaration();
decl.setSignatureFlag(true);
// role side:
MethodSpec spec = ast.newMethodSpec();
spec.setSignatureFlag(true);
spec.setName(ast.newSimpleName(accessorName));
if (!isSetter) {
spec.setReturnType2(imports.addImport(field.getType(), ast));
// no parameters
} else {
spec.setReturnType2(ast.newPrimitiveType(PrimitiveType.VOID));
createSetterParameter(unit, imports, ast, field, spec);
}
decl.setRoleMappingElement(spec);
// base side:
FieldAccessSpec fSpec = createFieldSpec(ast, imports, field, true);
decl.bindingOperator().setBindingModifier(isSetter ? Modifier.OT_SET_CALLOUT : Modifier.OT_GET_CALLOUT);
decl.setBaseMappingElement(fSpec);
if (settings.createComments) {
String delimiter= StubUtility.getLineDelimiterUsed(unit);
String string= CodeGeneration.getFieldComment(unit, declaringType, field.getName(), delimiter);
if (string != null) {
Javadoc javadoc= (Javadoc) rewrite.createStringPlaceholder(string, ASTNode.JAVADOC);
decl.setJavadoc(javadoc);
}
}
return decl;
}
public static FieldAccessSpec createFieldSpec(AST ast, ImportRewrite imports, IVariableBinding field, boolean hasSignature)
{
FieldAccessSpec fSpec= ast.newFieldAccessSpec();
fSpec.setSignatureFlag(hasSignature);
fSpec.setName(ast.newSimpleName(field.getName()));
fSpec.setFieldType(imports.addImport(field.getType(), ast));
return fSpec;
}
/** This method is inspired by createImplementationStub(..), but much leaner. */
public static MethodSpec createMethodSpec(ICompilationUnit unit,
ASTRewrite rewrite,
ImportRewrite imports,
ImportRewriteContext context,
AST ast,
IMethodBinding binding,
boolean hasSignature,
String type,
CodeGenerationSettings settings)
throws CoreException
{
MethodSpec spec = ast.newMethodSpec();
spec.setSignatureFlag(hasSignature);
spec.setName(ast.newSimpleName(binding.getName()));
if (!hasSignature)
return spec; // nothing more to do
// no type parameters
spec.setReturnType2(imports.addImport(binding.getReturnType(), ast));
// this helps to reuse some code regarding methods:
MethodDeclaration method = ast.newMethodDeclaration();
List parameters= getDefault().createParameters(unit.getJavaProject(), imports, context, ast, binding, method);
spec.parameters().addAll(ASTNode.copySubtrees(ast, parameters)); // copy to re-parent
return spec;
}
static void createSetterParameter(ICompilationUnit unit, ImportRewrite imports, AST ast, IVariableBinding field, MethodSpec decl)
{
List parameters= decl.parameters();
SingleVariableDeclaration var= ast.newSingleVariableDeclaration();
var.setType(imports.addImport(field.getType(), ast));
var.setName(ast.newSimpleName(field.getName()));
parameters.add(var);
}
}