• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package spechelper;
17 
18 import org.eclipse.jdt.core.Flags;
19 import org.eclipse.jdt.core.ICompilationUnit;
20 import org.eclipse.jdt.core.IJavaProject;
21 import org.eclipse.jdt.core.IMethod;
22 import org.eclipse.jdt.core.IType;
23 import org.eclipse.jdt.core.ITypeParameter;
24 import org.eclipse.jdt.core.JavaModelException;
25 import org.eclipse.jdt.core.Signature;
26 import org.eclipse.jdt.core.dom.AST;
27 import org.eclipse.jdt.core.dom.ASTParser;
28 import org.eclipse.jdt.core.dom.ASTVisitor;
29 import org.eclipse.jdt.core.dom.CompilationUnit;
30 import org.eclipse.jdt.core.dom.Expression;
31 import org.eclipse.jdt.core.dom.ITypeBinding;
32 import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
33 import org.eclipse.jdt.internal.ui.JavaPlugin;
34 import org.eclipse.jdt.ui.JavaElementLabelProvider;
35 import org.eclipse.jface.dialogs.IDialogConstants;
36 import org.eclipse.jface.dialogs.MessageDialog;
37 import org.eclipse.swt.widgets.Shell;
38 import org.eclipse.ui.IEditorInput;
39 import org.eclipse.ui.IEditorPart;
40 import org.eclipse.ui.PlatformUI;
41 import org.eclipse.ui.dialogs.ElementListSelectionDialog;
42 
43 import java.util.ArrayList;
44 import java.util.List;
45 
46 /**
47  *
48  */
49 public class MethodSelector {
50 
obtainReplacement(String buffer)51     public String obtainReplacement(String buffer) {
52         IMethod method = selectMethod();
53         // if user did cancel the selection
54         if (method == null) {
55             return null;
56         }
57 
58         // see if we are already in a annotation:
59         // if yes -> only dump the testtarget annotation, not the complete
60         // TestInfo
61         // (could not easily find this out with CompilationUnit, since inserting
62         // a :
63         // broke the AST - maybe use WorkingCopy and so on,
64         // but for now: do it with simple String analysis
65         boolean shortOnly = false;
66         int annotPos = buffer.lastIndexOf("@TestInfo");
67         // the latest annotation - count "(" ")" pairs - if not the same count
68         // we assume to be in the annotation (H: code compiles fine)
69         if (annotPos != -1) {
70             String sub = buffer.substring(annotPos);
71             // only consider the latest 6 lines for the annotation to occur
72             // (6 = range within which the annotation @TestTarget
73             // must occur, but out of range to reach the annotation from the
74             // previous method - ah i'd prefer working with compilationUnit...
75             String[] lines = sub.split("\n");
76             for (int i = lines.length - 6; i < lines.length; i++) {
77                 String line = lines[i];
78                 if (line.contains("@TestTarget")) {
79                     shortOnly = true;
80                 }
81             }
82         }
83 
84         return generateAnnotation(shortOnly, method);
85     }
86 
87 
generateAnnotation(boolean shortOnly, IMethod method)88     private String generateAnnotation(boolean shortOnly, IMethod method) {
89         String[] ptypes = method.getParameterTypes();
90         String param = "";
91         for (int i = 0; i < ptypes.length; i++) {
92             String ptype = ptypes[i];
93             String sig = Signature.toString(ptype);
94             // kind of a hack: convert all Generic Type args to Object, or to
95             // its bound Type
96             if (sig.length() == 1) {
97                 ITypeParameter tps = method.getTypeParameter(sig);
98                 sig = "Object";
99 
100                 if (tps != null && tps.exists()) {
101                     try {
102                         String[] bounds = tps.getBounds();
103                         if (bounds.length > 0) {
104                             sig = bounds[0];
105                         }
106                     } catch (JavaModelException e) {
107                         e.printStackTrace();
108                     }
109 
110                 }
111             }
112             // omit type signature
113             sig = sig.replaceAll("<.*>", "");
114             param += (i > 0 ? ", " : "") + sig + ".class";
115         }
116         String IND = "    ";
117 
118         String targ = "@TestTarget(\n" + IND + "      methodName = \""
119                 + method.getElementName() + "\",\n" + IND
120                 + "      methodArgs = {" + param + "}\n" + IND + "    )\n";
121 
122         String s;
123         if (shortOnly) {
124             s = targ;
125         } else {
126 
127             s = "@TestInfo(\n" + IND + "  status = TestStatus.TBR,\n" + IND
128                     + "  notes = \"\",\n" + IND + "  targets = {\n" + IND
129                     + "    " + targ + IND + "})";
130         }
131         return s;
132     }
133 
selectMethod()134     private IMethod selectMethod() {
135         IEditorPart part = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
136                 .getActivePage().getActiveEditor();
137         Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
138                 .getShell();
139         IEditorInput ei = part.getEditorInput();
140         final ICompilationUnit cu = JavaPlugin.getDefault()
141                 .getWorkingCopyManager().getWorkingCopy(ei);
142         // cu != null since we register only for java/javadoc completion
143         // proposals
144         ASTParser parser = ASTParser.newParser(AST.JLS3);
145         parser.setSource(cu);
146         parser.setResolveBindings(true);
147         CompilationUnit unit = (CompilationUnit) parser.createAST(null);
148 
149         class MHolder {
150             IMethod method;
151         }
152         final MHolder mholder = new MHolder();
153 
154         class FHolder {
155             boolean foundClassAnnotation;
156         }
157         final FHolder fholder = new FHolder();
158 
159         unit.accept(new ASTVisitor() {
160             public boolean visit(SingleMemberAnnotation node) {
161                 String name = node.getTypeName().getFullyQualifiedName();
162                 if (!name.equals("TestTargetClass")) {
163                     return false;
164                 }
165                 fholder.foundClassAnnotation = true;
166                 Expression targetClassE = node.getValue();
167                 ITypeBinding ty = targetClassE.resolveTypeBinding();
168                 if (ty == null) {
169                     return false;
170                 }
171                 ITypeBinding[] classTypes = ty.getTypeArguments();
172                 if (classTypes.length > 0) {
173                     ITypeBinding tp = classTypes[0];
174                     String qname = tp.getQualifiedName();
175                     System.out.println("qname:" + qname);
176                     IJavaProject myProject = cu.getJavaProject();
177                     try {
178                         IType myType = myProject.findType(qname);
179                         if (myType != null) {
180                             Shell parent = PlatformUI.getWorkbench()
181                                     .getActiveWorkbenchWindow().getShell();
182                             ElementListSelectionDialog dialog = new ElementListSelectionDialog(
183                                     parent,
184                                     new JavaElementLabelProvider(
185                                             JavaElementLabelProvider.SHOW_PARAMETERS
186                                                     | JavaElementLabelProvider.SHOW_OVERLAY_ICONS
187                                                     | JavaElementLabelProvider.SHOW_RETURN_TYPE));
188                             // restrict to public/protected methods only
189                             IMethod[] allMeth = myType.getMethods();
190                             List<IMethod> pubproMethods = new ArrayList<IMethod>();
191                             for (int i = 0; i < allMeth.length; i++) {
192                                 IMethod method = allMeth[i];
193                                 if ((method.getFlags() & (Flags.AccPublic | Flags.AccProtected)) != 0) {
194                                     pubproMethods.add(method);
195                                 }
196                             }
197                             IMethod[] res = pubproMethods
198                                     .toArray(new IMethod[pubproMethods.size()]);
199                             dialog.setIgnoreCase(true);
200                             dialog.setBlockOnOpen(true);
201                             dialog.setElements(res);//
202                             dialog.setFilter("");
203                             dialog.setTitle(qname);
204                             if (dialog.open() != IDialogConstants.CANCEL_ID) {
205                                 Object[] types = dialog.getResult();
206                                 System.out.println("selected:" + types[0]);
207                                 IMethod method = (IMethod) types[0];
208                                 mholder.method = method;
209 
210                             } else {
211                                 // System.out.println("cancelled!!");
212                             }
213                         }
214                     } catch (JavaModelException e) {
215                         e.printStackTrace();
216                     }
217                 }
218                 return true;
219             }
220         });
221         if (!fholder.foundClassAnnotation) {
222             MessageDialog.openInformation(shell, "Class Annotation missing",
223                     "@TestTargetClass(...) is missing");
224             return null;
225         }
226         return mholder.method;
227     }
228 }
229