--- /dev/null
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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.
+ */
+package spechelper;
+
+import org.eclipse.jdt.core.Flags;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.ITypeParameter;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTParser;
+import org.eclipse.jdt.core.dom.ASTVisitor;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
+import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.ui.JavaElementLabelProvider;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.ElementListSelectionDialog;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ */
+public class MethodSelector {
+
+ public String obtainReplacement(String buffer) {
+ IMethod method = selectMethod();
+ // if user did cancel the selection
+ if (method == null) {
+ return null;
+ }
+
+ // see if we are already in a annotation:
+ // if yes -> only dump the testtarget annotation, not the complete
+ // TestInfo
+ // (could not easily find this out with CompilationUnit, since inserting
+ // a :
+ // broke the AST - maybe use WorkingCopy and so on,
+ // but for now: do it with simple String analysis
+ boolean shortOnly = false;
+ int annotPos = buffer.lastIndexOf("@TestInfo");
+ // the latest annotation - count "(" ")" pairs - if not the same count
+ // we assume to be in the annotation (H: code compiles fine)
+ if (annotPos != -1) {
+ String sub = buffer.substring(annotPos);
+ // only consider the latest 6 lines for the annotation to occur
+ // (6 = range within which the annotation @TestTarget
+ // must occur, but out of range to reach the annotation from the
+ // previous method - ah i'd prefer working with compilationUnit...
+ String[] lines = sub.split("\n");
+ for (int i = lines.length - 6; i < lines.length; i++) {
+ String line = lines[i];
+ if (line.contains("@TestTarget")) {
+ shortOnly = true;
+ }
+ }
+ }
+
+ return generateAnnotation(shortOnly, method);
+ }
+
+
+ private String generateAnnotation(boolean shortOnly, IMethod method) {
+ String[] ptypes = method.getParameterTypes();
+ String param = "";
+ for (int i = 0; i < ptypes.length; i++) {
+ String ptype = ptypes[i];
+ String sig = Signature.toString(ptype);
+ // kind of a hack: convert all Generic Type args to Object, or to
+ // its bound Type
+ if (sig.length() == 1) {
+ ITypeParameter tps = method.getTypeParameter(sig);
+ sig = "Object";
+
+ if (tps != null && tps.exists()) {
+ try {
+ String[] bounds = tps.getBounds();
+ if (bounds.length > 0) {
+ sig = bounds[0];
+ }
+ } catch (JavaModelException e) {
+ e.printStackTrace();
+ }
+
+ }
+ }
+ // omit type signature
+ sig = sig.replaceAll("<.*>", "");
+ param += (i > 0 ? ", " : "") + sig + ".class";
+ }
+ String IND = " ";
+
+ String targ = "@TestTarget(\n" + IND + " methodName = \""
+ + method.getElementName() + "\",\n" + IND
+ + " methodArgs = {" + param + "}\n" + IND + " )\n";
+
+ String s;
+ if (shortOnly) {
+ s = targ;
+ } else {
+
+ s = "@TestInfo(\n" + IND + " status = TestStatus.TBR,\n" + IND
+ + " notes = \"\",\n" + IND + " targets = {\n" + IND
+ + " " + targ + IND + "})";
+ }
+ return s;
+ }
+
+ private IMethod selectMethod() {
+ IEditorPart part = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
+ .getActivePage().getActiveEditor();
+ Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
+ .getShell();
+ IEditorInput ei = part.getEditorInput();
+ final ICompilationUnit cu = JavaPlugin.getDefault()
+ .getWorkingCopyManager().getWorkingCopy(ei);
+ // cu != null since we register only for java/javadoc completion
+ // proposals
+ ASTParser parser = ASTParser.newParser(AST.JLS3);
+ parser.setSource(cu);
+ parser.setResolveBindings(true);
+ CompilationUnit unit = (CompilationUnit) parser.createAST(null);
+
+ class MHolder {
+ IMethod method;
+ }
+ final MHolder mholder = new MHolder();
+
+ class FHolder {
+ boolean foundClassAnnotation;
+ }
+ final FHolder fholder = new FHolder();
+
+ unit.accept(new ASTVisitor() {
+ public boolean visit(SingleMemberAnnotation node) {
+ String name = node.getTypeName().getFullyQualifiedName();
+ if (!name.equals("TestTargetClass")) {
+ return false;
+ }
+ fholder.foundClassAnnotation = true;
+ Expression targetClassE = node.getValue();
+ ITypeBinding ty = targetClassE.resolveTypeBinding();
+ if (ty == null) {
+ return false;
+ }
+ ITypeBinding[] classTypes = ty.getTypeArguments();
+ if (classTypes.length > 0) {
+ ITypeBinding tp = classTypes[0];
+ String qname = tp.getQualifiedName();
+ System.out.println("qname:" + qname);
+ IJavaProject myProject = cu.getJavaProject();
+ try {
+ IType myType = myProject.findType(qname);
+ if (myType != null) {
+ Shell parent = PlatformUI.getWorkbench()
+ .getActiveWorkbenchWindow().getShell();
+ ElementListSelectionDialog dialog = new ElementListSelectionDialog(
+ parent,
+ new JavaElementLabelProvider(
+ JavaElementLabelProvider.SHOW_PARAMETERS
+ | JavaElementLabelProvider.SHOW_OVERLAY_ICONS
+ | JavaElementLabelProvider.SHOW_RETURN_TYPE));
+ // restrict to public/protected methods only
+ IMethod[] allMeth = myType.getMethods();
+ List<IMethod> pubproMethods = new ArrayList<IMethod>();
+ for (int i = 0; i < allMeth.length; i++) {
+ IMethod method = allMeth[i];
+ if ((method.getFlags() & (Flags.AccPublic | Flags.AccProtected)) != 0) {
+ pubproMethods.add(method);
+ }
+ }
+ IMethod[] res = pubproMethods
+ .toArray(new IMethod[pubproMethods.size()]);
+ dialog.setIgnoreCase(true);
+ dialog.setBlockOnOpen(true);
+ dialog.setElements(res);//
+ dialog.setFilter("");
+ dialog.setTitle(qname);
+ if (dialog.open() != IDialogConstants.CANCEL_ID) {
+ Object[] types = dialog.getResult();
+ System.out.println("selected:" + types[0]);
+ IMethod method = (IMethod) types[0];
+ mholder.method = method;
+
+ } else {
+ // System.out.println("cancelled!!");
+ }
+ }
+ } catch (JavaModelException e) {
+ e.printStackTrace();
+ }
+ }
+ return true;
+ }
+ });
+ if (!fholder.foundClassAnnotation) {
+ MessageDialog.openInformation(shell, "Class Annotation missing",
+ "@TestTargetClass(...) is missing");
+ return null;
+ }
+ return mholder.method;
+ }
+}