Java tutorial
/* * Copyright 2008 the Seasar Foundation and the Others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language * governing permissions and limitations under the License. * * This is a program source code derived from the Eclipse Software. * An original copyright notice is as follows. ******************************************************************************* * Copyright (c) 2000, 2006 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.seasar.s2junit4plugin.wizard; import org.eclipse.text.edits.MalformedTreeException; import org.eclipse.text.edits.TextEdit; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.Document; import org.eclipse.jdt.core.Flags; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.Signature; import org.eclipse.jdt.core.ToolFactory; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.IBinding; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.formatter.CodeFormatter; import org.eclipse.jdt.core.formatter.IndentManipulation; import org.eclipse.jdt.internal.corext.util.JavaModelUtil; import org.eclipse.jdt.ui.CodeGeneration; import org.eclipse.jdt.ui.PreferenceConstants; import org.seasar.s2junit4plugin.wizard.NewS2JUnit4TypeWizardPage.ImportsManager; /** * Utility methods for code generation. * TODO: some methods are duplicated from org.eclipse.jdt.ui */ public class S2JUnit4StubUtility { public static GenStubSettings getCodeGenerationSettings(IJavaProject project) { return new GenStubSettings(project); } public static class GenStubSettings { public boolean callSuper; public boolean methodOverwrites; public boolean noBody; public boolean createComments; public boolean useKeywordThis; public final int tabWidth; public GenStubSettings(IJavaProject project) { this.createComments = Boolean .valueOf(PreferenceConstants.getPreference(PreferenceConstants.CODEGEN_ADD_COMMENTS, project)) .booleanValue(); this.useKeywordThis = Boolean .valueOf(PreferenceConstants.getPreference(PreferenceConstants.CODEGEN_KEYWORD_THIS, project)) .booleanValue(); this.tabWidth = IndentManipulation.getTabWidth(project.getOptions(true)); } } public static String formatCompilationUnit(IJavaProject project, String sourceString, String lineDelim) { return codeFormat(project, sourceString, CodeFormatter.K_COMPILATION_UNIT, 0, lineDelim); } public static String codeFormat(IJavaProject project, String sourceString, int kind, int initialIndentationLevel, String lineDelim) { CodeFormatter formatter = ToolFactory.createCodeFormatter(project.getOptions(true)); TextEdit edit = formatter.format(kind, sourceString, 0, sourceString.length(), initialIndentationLevel, lineDelim); if (edit != null) { Document doc = new Document(sourceString); try { edit.apply(doc); return doc.get(); } catch (MalformedTreeException e) { } catch (BadLocationException e) { } } return sourceString; } /** * Generates a stub. Given a template method, a stub with the same signature * will be constructed so it can be added to a type. * @param destTypeName The name of the type to which the method will be added to (Used for the constructor) * @param method A method template (method belongs to different type than the parent) * @param settings Options as defined above (GENSTUB_*) * @param imports Imports required by the sub are added to the imports structure * @return The ynformatted stub * @throws JavaModelException */ public static String genStub(ICompilationUnit compilationUnit, String destTypeName, IMethod method, GenStubSettings settings, String extraAnnotations, ImportsManager imports) throws CoreException { IType declaringtype = method.getDeclaringType(); StringBuffer buf = new StringBuffer(); String[] paramTypes = method.getParameterTypes(); String[] paramNames = method.getParameterNames(); String[] excTypes = method.getExceptionTypes(); String retTypeSig = method.getReturnType(); int lastParam = paramTypes.length - 1; String comment = null; if (settings.createComments) { if (method.isConstructor()) { comment = CodeGeneration.getMethodComment(compilationUnit, destTypeName, method.getElementName(), paramNames, excTypes, null, null, "\n"); //$NON-NLS-1$ } else { if (settings.methodOverwrites) { comment = CodeGeneration.getMethodComment(compilationUnit, destTypeName, method.getElementName(), paramNames, excTypes, retTypeSig, method, "\n"); //$NON-NLS-1$ } else { comment = CodeGeneration.getMethodComment(compilationUnit, destTypeName, method.getElementName(), paramNames, excTypes, retTypeSig, null, "\n"); //$NON-NLS-1$ } } } if (comment != null) { buf.append(comment).append('\n'); } if (extraAnnotations != null) { buf.append(extraAnnotations).append('\n'); } int flags = method.getFlags(); if (Flags.isPublic(flags) || (declaringtype.isInterface() && !settings.noBody)) { buf.append("public "); //$NON-NLS-1$ } else if (Flags.isProtected(flags)) { buf.append("protected "); //$NON-NLS-1$ } else if (Flags.isPrivate(flags)) { buf.append("private "); //$NON-NLS-1$ } if (Flags.isSynchronized(flags)) { buf.append("synchronized "); //$NON-NLS-1$ } if (Flags.isVolatile(flags)) { buf.append("volatile "); //$NON-NLS-1$ } if (Flags.isStrictfp(flags)) { buf.append("strictfp "); //$NON-NLS-1$ } if (Flags.isStatic(flags)) { buf.append("static "); //$NON-NLS-1$ } if (method.isConstructor()) { buf.append(destTypeName); } else { String retTypeFrm = Signature.toString(retTypeSig); if (!isBuiltInType(retTypeSig)) { resolveAndAdd(retTypeSig, declaringtype, imports); } buf.append(Signature.getSimpleName(retTypeFrm)); buf.append(' '); buf.append(method.getElementName()); } buf.append('('); for (int i = 0; i <= lastParam; i++) { String paramTypeSig = paramTypes[i]; String paramTypeFrm = Signature.toString(paramTypeSig); if (!isBuiltInType(paramTypeSig)) { resolveAndAdd(paramTypeSig, declaringtype, imports); } buf.append(Signature.getSimpleName(paramTypeFrm)); buf.append(' '); buf.append(paramNames[i]); if (i < lastParam) { buf.append(", "); //$NON-NLS-1$ } } buf.append(')'); int lastExc = excTypes.length - 1; if (lastExc >= 0) { buf.append(" throws "); //$NON-NLS-1$ for (int i = 0; i <= lastExc; i++) { String excTypeSig = excTypes[i]; String excTypeFrm = Signature.toString(excTypeSig); resolveAndAdd(excTypeSig, declaringtype, imports); buf.append(Signature.getSimpleName(excTypeFrm)); if (i < lastExc) { buf.append(", "); //$NON-NLS-1$ } } } if (settings.noBody) { buf.append(";\n\n"); //$NON-NLS-1$ } else { buf.append(" {\n\t"); //$NON-NLS-1$ if (!settings.callSuper) { if (retTypeSig != null && !retTypeSig.equals(Signature.SIG_VOID)) { buf.append('\t'); if (!isBuiltInType(retTypeSig) || Signature.getArrayCount(retTypeSig) > 0) { buf.append("return null;\n\t"); //$NON-NLS-1$ } else if (retTypeSig.equals(Signature.SIG_BOOLEAN)) { buf.append("return false;\n\t"); //$NON-NLS-1$ } else { buf.append("return 0;\n\t"); //$NON-NLS-1$ } } } else { buf.append('\t'); if (!method.isConstructor()) { if (!Signature.SIG_VOID.equals(retTypeSig)) { buf.append("return "); //$NON-NLS-1$ } buf.append("super."); //$NON-NLS-1$ buf.append(method.getElementName()); } else { buf.append("super"); //$NON-NLS-1$ } buf.append('('); for (int i = 0; i <= lastParam; i++) { buf.append(paramNames[i]); if (i < lastParam) { buf.append(", "); //$NON-NLS-1$ } } buf.append(");\n\t"); //$NON-NLS-1$ } buf.append("}\n\n"); //$NON-NLS-1$ } return buf.toString(); } private static boolean isBuiltInType(String typeName) { char first = Signature.getElementType(typeName).charAt(0); return (first != Signature.C_RESOLVED && first != Signature.C_UNRESOLVED); } private static void resolveAndAdd(String refTypeSig, IType declaringType, ImportsManager imports) throws JavaModelException { String resolvedTypeName = JavaModelUtil.getResolvedTypeName(refTypeSig, declaringType); if (resolvedTypeName != null) { imports.addImport(resolvedTypeName); } } public static String getTodoTaskTag(IJavaProject project) { String markers = null; if (project == null) { markers = JavaCore.getOption(JavaCore.COMPILER_TASK_TAGS); } else { markers = project.getOption(JavaCore.COMPILER_TASK_TAGS, true); } if (markers != null && markers.length() > 0) { int idx = markers.indexOf(','); if (idx == -1) { return markers; } return markers.substring(0, idx); } return null; } /* * Evaluates if a member (possible from another package) is visible from * elements in a package. */ public static boolean isVisible(IMember member, IPackageFragment pack) throws JavaModelException { int type = member.getElementType(); if (type == IJavaElement.INITIALIZER || (type == IJavaElement.METHOD && member.getElementName().startsWith("<"))) { //$NON-NLS-1$ return false; } int otherflags = member.getFlags(); IType declaringType = member.getDeclaringType(); if (Flags.isPublic(otherflags) || (declaringType != null && declaringType.isInterface())) { return true; } else if (Flags.isPrivate(otherflags)) { return false; } IPackageFragment otherpack = (IPackageFragment) member.getAncestor(IJavaElement.PACKAGE_FRAGMENT); return (pack != null && otherpack != null && pack.getElementName().equals(otherpack.getElementName())); } private static boolean isVersionLessThan(String version1, String version2) { return version1.compareTo(version2) < 0; } public static boolean is50OrHigher(IJavaProject project) { return !isVersionLessThan(project.getOption(JavaCore.COMPILER_COMPLIANCE, true), JavaCore.VERSION_1_5); } public static String[] getParameterTypeNamesForSeeTag(IMethod overridden) { try { ASTParser parser = ASTParser.newParser(AST.JLS3); parser.setProject(overridden.getJavaProject()); IBinding[] bindings = parser.createBindings(new IJavaElement[] { overridden }, null); if (bindings.length == 1 && bindings[0] instanceof IMethodBinding) { return getParameterTypeNamesForSeeTag((IMethodBinding) bindings[0]); } } catch (IllegalStateException e) { // method does not exist } // fall back code. Not good for generic methods! String[] paramTypes = overridden.getParameterTypes(); String[] paramTypeNames = new String[paramTypes.length]; for (int i = 0; i < paramTypes.length; i++) { paramTypeNames[i] = Signature.toString(Signature.getTypeErasure(paramTypes[i])); } return paramTypeNames; } private static String[] getParameterTypeNamesForSeeTag(IMethodBinding binding) { ITypeBinding[] typeBindings = binding.getParameterTypes(); String[] result = new String[typeBindings.length]; for (int i = 0; i < result.length; i++) { ITypeBinding curr = typeBindings[i]; if (curr.isTypeVariable()) { curr = curr.getErasure(); // in Javadoc only use type variable erasure } curr = curr.getTypeDeclaration(); // no parameterized types result[i] = curr.getQualifiedName(); } return result; } }