auto import from //branches/cupcake_rel/...@138607
diff --git a/tools/test-progress-new/src/testprogress2/TestTargetNew.java b/tools/test-progress-new/src/testprogress2/TestTargetNew.java
new file mode 100644
index 0000000..6102614
--- /dev/null
+++ b/tools/test-progress-new/src/testprogress2/TestTargetNew.java
@@ -0,0 +1,373 @@
+/*
+ * 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 testprogress2;
+
+import com.sun.javadoc.AnnotationDesc;
+import com.sun.javadoc.AnnotationValue;
+import com.sun.javadoc.ClassDoc;
+import com.sun.javadoc.ExecutableMemberDoc;
+import com.sun.javadoc.FieldDoc;
+import com.sun.javadoc.Parameter;
+import com.sun.javadoc.ParameterizedType;
+import com.sun.javadoc.Type;
+import com.sun.javadoc.TypeVariable;
+import com.sun.javadoc.AnnotationDesc.ElementValuePair;
+
+import testprogress2.TestMethodInformation.Level;
+
+/**
+ * holder for a TestTargetNew annotation
+ */
+public class TestTargetNew {
+ private final Originator originator;
+
+ private Level level = null;
+
+ private String notes = null;
+
+ /*
+ * method or constructor of target class
+ */
+ private ExecutableMemberDoc targetMethod = null;
+
+ /*
+ * only set if the target points -only- to a class, not to a method. e.g for
+ * special "!..." targets
+ */
+ private ClassDoc targetClass = null;
+
+ /*
+ * read from annotation, e.g. foobar(java.lang.String)
+ */
+ private String readMethodSignature = null;
+
+ /*
+ * e.g. foobar
+ */
+ private String readMethodName = null;
+
+ /*
+ * read from annotation
+ */
+ private ClassDoc readTargetClass = null;
+
+ private boolean havingProblems = false;
+
+ private TestTargetNew(Originator originator) {
+ this.originator = originator;
+ }
+
+ /**
+ * @param originator the origin (class or method)
+ * @param ttn the annotation (testtargetnew)
+ * @param classLevelTargetClass the default target class as given in the
+ * testtargetclass annotation
+ */
+ public TestTargetNew(Originator originator, AnnotationDesc ttn,
+ ClassDoc classLevelTargetClass) {
+ this.originator = originator;
+ parseTargetClassAndMethodSignature(ttn, classLevelTargetClass);
+ // post: readMethod, readMethodSignature and readTargetClass are now set
+
+ // test for artificial method targets
+ if (readMethodName.startsWith("!")) {
+ targetMethod = null;
+ targetClass = readTargetClass;
+ // level = Level.ADDITIONAL;
+ // notes already set
+ notes = "target: " + readMethodName
+ + (notes != null ? ", " + "notes: " + notes : "");
+
+ } else if (level == Level.TODO) {
+ notes = "TODO :" + notes;
+ havingProblems = true;
+ } else {
+ // prepare method target:
+ // if the signature contains a "." then the prefix is used as a
+ // reference
+ // to an inner class. This is an alternative to using the clazz
+ // attribute in cases where the class is an inner protected class,
+ // because then the inner class is not visible for the compiler at
+ // the
+ // place of the annotation.
+ // e.g. clazz = Certificate.CertificateRep.class does not work,
+ // so we use clazz = Certificate.class (enclosing class), and method
+ // "Certificate.CertificateRep.<methodHere>", e.g.
+ // "CertificateRep.CertificateRep"
+ // to denote the constructor of the inner protected class
+ // CertificateRep
+ // within Certificate
+ int dotPos = readMethodName.lastIndexOf('.');
+ if (dotPos != -1) {
+ String prefixClassName = readMethodName.substring(0, dotPos);
+ readMethodName = readMethodName.substring(dotPos + 1);
+ ClassDoc[] iCs = readTargetClass.innerClasses();
+ for (ClassDoc iC : iCs) {
+ if (iC.name().equals(prefixClassName)) {
+ readTargetClass = iC;
+ break;
+ }
+ }
+ }
+
+ String methodAndSig = readMethodName + readMethodSignature;
+ ExecutableMemberDoc tmeth = findMethodSignatureIn(methodAndSig,
+ readTargetClass);
+ // we need this double test for the note below
+ if (tmeth == null) {
+ // a) wrong signature or
+ // b) a testMethod in a superclass or superinterface, ok also
+ tmeth = findTargetMethodInSelfAndSupers(methodAndSig,
+ readTargetClass);
+ if (tmeth != null) {
+ if (notes == null)
+ notes = "";
+ notes += "- targetmethod (" + tmeth + ") was found in a "
+ + "superclass/superinterface of the target<br>";
+ }
+ }
+ if (tmeth != null) {
+ // found
+ targetMethod = tmeth;
+ } else {
+ havingProblems = true;
+ notes = "From " + originator.asString()
+ + " -> could not resolve " + "targetMethod for class "
+ + readTargetClass + ", " + "annotation was:" + ttn
+ + ", testMethodSig " + "= " + methodAndSig + "<br>";
+ System.err.println(">>> warning: " + notes);
+ }
+ }
+ }
+
+ private ExecutableMemberDoc findMethodSignatureIn(String sig,
+ ClassDoc targetClass) {
+ ExecutableMemberDoc targetMethod = null;
+ // find the matching method in the target class, check all methods
+ for (ExecutableMemberDoc mdoc : targetClass.methods()) {
+ if (equalsSignature(mdoc, sig)) {
+ return mdoc;
+ }
+ }
+ // check constructors, too
+ for (ExecutableMemberDoc mdoc : targetClass.constructors()) {
+ if (equalsSignature(mdoc, sig)) {
+ return mdoc;
+ }
+ }
+ return null;
+ }
+
+ private ExecutableMemberDoc findTargetMethodInSelfAndSupers(String sig,
+ ClassDoc targetClass) {
+ ExecutableMemberDoc mem = findMethodSignatureIn(sig, targetClass);
+ if (mem != null) {
+ return mem;
+ }
+
+ // else visit parent class or parent interface(s)
+ ClassDoc[] ifs = targetClass.interfaces();
+ for (int i = 0; i < ifs.length; i++) {
+ ClassDoc iface = ifs[i];
+ mem = findTargetMethodInSelfAndSupers(sig, iface);
+ if (mem != null) {
+ return mem;
+ }
+ }
+
+ ClassDoc superclass = targetClass.superclass();
+ if (superclass != null) {
+ mem = findTargetMethodInSelfAndSupers(sig, superclass);
+ if (mem != null) {
+ return mem;
+ }
+ }
+ return null;
+ }
+
+ private void parseTargetClassAndMethodSignature(AnnotationDesc targetAnnot,
+ ClassDoc targetClass) {
+ ElementValuePair[] pairs = targetAnnot.elementValues();
+ String methodName = null;
+ String args = "";
+ for (ElementValuePair kval : pairs) {
+ if (kval.element().name().equals("method")) {
+ methodName = (String)kval.value().value();
+ } else if (kval.element().name().equals("clazz")) {
+ // optional: a different target class than the test-class-level
+ // default.
+ Object obj = kval.value().value();
+ if (obj instanceof ClassDoc) {
+ targetClass = (ClassDoc)obj;
+ } else if (obj instanceof ParameterizedType) {
+ targetClass = ((ParameterizedType)obj).asClassDoc();
+ } else {
+ throw new RuntimeException("annotation elem value is of "
+ + "type " + obj.getClass().getName() + " target "
+ + "annotation = " + targetAnnot);
+ }
+ } else if (kval.element().name().equals("args")) {
+ AnnotationValue[] vals = (AnnotationValue[])kval.value()
+ .value();
+ for (int i = 0; i < vals.length; i++) {
+ AnnotationValue arg = vals[i];
+ String argV;
+ // TODO: we should be able to use Type.asClassDoc() here
+ if (arg.value() instanceof ClassDoc) {
+ ClassDoc cd = (ClassDoc)arg.value();
+ argV = cd.qualifiedName();
+ } else { // primitive type or array type
+ // is there a nicer way to do this?
+ argV = arg.toString();
+ }
+ // strip .class out of args since signature does not contain
+ // those
+ if (argV.endsWith(".class")) {
+ argV = argV.substring(0, argV.length() - 6);
+ }
+ args += (i > 0 ? "," : "") + argV;
+ }
+ } else if (kval.element().name().equals("level")) {
+ AnnotationValue lev = kval.value();
+ FieldDoc fd = (FieldDoc)lev.value();
+ String slevel = fd.name();
+
+ try {
+ level = Enum.valueOf(Level.class, slevel);
+ } catch (IllegalArgumentException iae) {
+ throw new RuntimeException("COMPILE ERROR!!! enum "
+ + slevel + " used in targetMethod for class "
+ + "\"+targetClass+\", "
+ + "annotation was:\"+targetAnnot+\", "
+ + "testMethod = \"+methodDoc.toString()");
+ }
+ } else if (kval.element().name().equals("notes")) {
+ notes = (String)kval.value().value();
+ if (notes.equals("")) {
+ notes = null;
+ }
+ }
+ }
+
+ // String refSig = methodName + "(" + args + ")";
+ // both methodName and methodArgs != null because of Annotation
+ // definition
+ this.readTargetClass = targetClass;
+ this.readMethodSignature = "(" + args + ")";
+ this.readMethodName = methodName;
+ }
+
+ private boolean equalsSignature(ExecutableMemberDoc mdoc,
+ String refSignature) {
+ Parameter[] params = mdoc.parameters();
+ String targs = "";
+ for (int i = 0; i < params.length; i++) {
+ Parameter parameter = params[i];
+ // check for generic type types
+ Type ptype = parameter.type();
+
+ TypeVariable typeVar = ptype.asTypeVariable();
+ String ptname;
+ if (typeVar != null) {
+ ptname = "java.lang.Object"; // the default fallback
+ Type[] bounds = typeVar.bounds();
+ if (bounds.length > 0) {
+ ClassDoc typeClass = bounds[0].asClassDoc();
+ ptname = typeClass.qualifiedName();
+ }
+ String dim = ptype.dimension();
+ if (dim != null && dim.length() > 0) {
+ ptname += dim;
+ }
+ } else {
+ // regular var
+ // ptname = parameter.type().qualifiedTypeName();
+ ptname = parameter.type().toString();
+
+ // System.out.println("quali:"+ptname);
+ // ptname = parameter.typeName();
+ // omit type signature
+ ptname = ptname.replaceAll("<.*>", "");
+ }
+ targs += (i > 0 ? "," : "") + ptname;
+ }
+
+ String methodName = mdoc.name();
+ int lastDot = methodName.lastIndexOf('.');
+ if (lastDot != -1) {
+ // we have a inner class constructor
+ // shrink the name to just name the constructor
+ methodName = methodName.substring(lastDot + 1);
+ }
+
+ String testSig = methodName + "(" + targs + ")";
+
+ // return testSig.equals(refSignature);
+ if (testSig.equals(refSignature)) {
+ // System.out.println("match!!!: ref = "+refSignature+",
+ // test = "+testSig);
+ return true;
+ } else {
+ // System.out.println("no match: ref = "+refSignature+",
+ // test = "+testSig);
+ return false;
+ }
+ }
+
+ public Level getLevel() {
+ return level;
+ }
+
+ public boolean isHavingProblems() {
+ return havingProblems;
+ }
+
+ public Originator getOriginator() {
+ return originator;
+ }
+
+ TestTargetNew cloneMe(String extraNote) {
+ TestTargetNew anew = new TestTargetNew(this.originator);
+ anew.level = this.level;
+ anew.notes = this.notes;
+ anew.targetMethod = this.targetMethod;
+ anew.readMethodSignature = this.readMethodSignature;
+ anew.readTargetClass = this.readTargetClass;
+
+ // mark indirectly tested method always as green, independent
+ // of the original status (to better estimate workload)
+ // anew.level = Level.COMPLETE;
+ anew.notes = extraNote + (notes != null ? ", " + notes : "");
+ return anew;
+ }
+
+ public ExecutableMemberDoc getTargetMethod() {
+ return targetMethod;
+ }
+
+ /**
+ * @return the class of the testtargetnew which method starts with "!", null
+ * otherwise
+ */
+ public ClassDoc getTargetClass() {
+ return targetClass;
+ }
+
+ public String getNotes() {
+ return notes;
+ }
+}