Source Code Cross Referenced for AbstractTestGenerator.java in  » IDE-Netbeans » junit » org » netbeans » modules » junit » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » junit » org.netbeans.modules.junit 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2008 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:
0042:        package org.netbeans.modules.junit;
0043:
0044:        import com.sun.source.tree.AnnotationTree;
0045:        import com.sun.source.tree.BlockTree;
0046:        import com.sun.source.tree.ClassTree;
0047:        import com.sun.source.tree.CompilationUnitTree;
0048:        import com.sun.source.tree.ExpressionStatementTree;
0049:        import com.sun.source.tree.ExpressionTree;
0050:        import com.sun.source.tree.IdentifierTree;
0051:        import com.sun.source.tree.LiteralTree;
0052:        import com.sun.source.tree.MethodInvocationTree;
0053:        import com.sun.source.tree.MethodTree;
0054:        import com.sun.source.tree.ModifiersTree;
0055:        import com.sun.source.tree.StatementTree;
0056:        import com.sun.source.tree.Tree;
0057:        import com.sun.source.tree.TypeParameterTree;
0058:        import com.sun.source.tree.VariableTree;
0059:        import com.sun.source.util.TreePath;
0060:        import java.io.IOException;
0061:        import java.util.ArrayList;
0062:        import java.util.Collections;
0063:        import java.util.EnumSet;
0064:        import java.util.HashMap;
0065:        import java.util.HashSet;
0066:        import java.util.Iterator;
0067:        import java.util.List;
0068:        import java.util.Map;
0069:        import java.util.Set;
0070:        import java.util.logging.Level;
0071:        import java.util.logging.Logger;
0072:        import javax.lang.model.element.Element;
0073:        import javax.lang.model.element.ElementKind;
0074:        import javax.lang.model.element.ExecutableElement;
0075:        import javax.lang.model.element.Modifier;
0076:        import javax.lang.model.element.TypeElement;
0077:        import javax.lang.model.element.VariableElement;
0078:        import javax.lang.model.type.TypeKind;
0079:        import javax.lang.model.type.TypeMirror;
0080:        import javax.lang.model.util.ElementFilter;
0081:        import javax.lang.model.util.Elements;
0082:        import javax.lang.model.util.Types;
0083:        import org.netbeans.api.java.source.CancellableTask;
0084:        import org.netbeans.api.java.source.ClasspathInfo;
0085:        import org.netbeans.api.java.source.Comment;
0086:        import org.netbeans.api.java.source.CompilationInfo;
0087:        import org.netbeans.api.java.source.ElementHandle;
0088:        import org.netbeans.api.java.source.JavaSource.Phase;
0089:        import org.netbeans.api.java.source.TreeMaker;
0090:        import org.netbeans.api.java.source.WorkingCopy;
0091:        import org.openide.ErrorManager;
0092:        import org.openide.util.NbBundle;
0093:        import static org.netbeans.modules.junit.TestCreator.ACCESS_MODIFIERS;
0094:
0095:        /**
0096:         * A base class for generators of JUnit test classes and test methods.
0097:         *
0098:         * @author  Marian Petras
0099:         */
0100:        abstract class AbstractTestGenerator implements 
0101:                CancellableTask<WorkingCopy> {
0102:
0103:            /**
0104:             * name of the 'instance' variable in the generated test method skeleton
0105:             *
0106:             * @see  #RESULT_VAR_NAME
0107:             * @see  #EXP_RESULT_VAR_NAME
0108:             */
0109:            private static final String INSTANCE_VAR_NAME = "instance"; //NOI18N
0110:            /**
0111:             * name of the 'result' variable in the generated test method skeleton
0112:             *
0113:             * @see  #EXP_RESULT_VAR_NAME
0114:             */
0115:            private static final String RESULT_VAR_NAME = "result"; //NOI18N
0116:            /**
0117:             * name of the 'expected result' variable in the generated test method
0118:             * skeleton
0119:             *
0120:             * @see  #RESULT_VAR_NAME
0121:             */
0122:            private static final String EXP_RESULT_VAR_NAME = "expResult"; //NOI18N
0123:            /**
0124:             * base for artificial names of variables
0125:             * (if there is no name to derive from)
0126:             */
0127:            private static final String ARTIFICAL_VAR_NAME_BASE = "arg"; //NOI18N
0128:            /** */
0129:            private static final EnumSet<Modifier> NO_MODIFIERS = EnumSet
0130:                    .noneOf(Modifier.class);
0131:
0132:            /**
0133:             * Returns {@code EnumSet} of all access modifiers.
0134:             * 
0135:             * @return  {@code EnumSet} of all access modifiers;
0136:             *          it is guaranteed that the returned set always contains
0137:             *          the same set of {@code Modifier}s, but the returned
0138:             *          instance may not always be the same
0139:             */
0140:            protected static EnumSet<Modifier> accessModifiers() {
0141:                /*
0142:                 * An alternative would be to create an instance of
0143:                 * unmodifiable Set<Modifier> (e.g. Collections.unmodifiableSet(...))
0144:                 * and always return this instance. But the instance would not be an
0145:                 * instance of (subclass of) EnumSet which would significantly slow down
0146:                 * many operations performed on it.
0147:                 */
0148:                return EnumSet.copyOf(ACCESS_MODIFIERS);
0149:            }
0150:
0151:            /**
0152:             * Returns an empty {@code EnumSet} of {@code Modifier}s.
0153:             * 
0154:             * @return  empty {@code EnumSet} of all {@code Modifier}s;
0155:             *          it is guaranteed that the returned set is always empty
0156:             *          but the returned instance may not always be the same
0157:             */
0158:            protected static EnumSet<Modifier> noModifiers() {
0159:                /*
0160:                 * An alternative would be to create an instance of
0161:                 * unmodifiable Set<Modifier> (e.g. Collections.<Modifier>emptySet())
0162:                 * and always return that instance. But the instance would not be an
0163:                 * instance of (subclass of) EnumSet which would significantly slow down
0164:                 * many operations performed on it.
0165:                 */
0166:                return EnumSet.copyOf(NO_MODIFIERS);
0167:            }
0168:
0169:            /** */
0170:            protected final TestGeneratorSetup setup;
0171:
0172:            private final List<ElementHandle<TypeElement>> srcTopClassElemHandles;
0173:
0174:            private final List<String> suiteMembers;
0175:
0176:            private final boolean isNewTestClass;
0177:
0178:            private List<String> processedClassNames;
0179:
0180:            /**
0181:             * cached value of <code>JUnitSettings.getGenerateMainMethodBody()</code>
0182:             */
0183:            private String initialMainMethodBody;
0184:
0185:            private volatile boolean cancelled = false;
0186:
0187:            /**
0188:             * Used when creating a new empty test class.
0189:             */
0190:            protected AbstractTestGenerator(TestGeneratorSetup setup) {
0191:                this .setup = setup;
0192:                this .srcTopClassElemHandles = null;
0193:                this .suiteMembers = null;
0194:                this .isNewTestClass = true; //value not used
0195:            }
0196:
0197:            /**
0198:             * Used when creating a test class for a given source class
0199:             * or when creating a test suite.
0200:             */
0201:            protected AbstractTestGenerator(TestGeneratorSetup setup,
0202:                    List<ElementHandle<TypeElement>> srcTopClassHandles,
0203:                    List<String> suiteMembers, boolean isNewTestClass) {
0204:                this .setup = setup;
0205:                this .srcTopClassElemHandles = srcTopClassHandles;
0206:                this .suiteMembers = suiteMembers;
0207:                this .isNewTestClass = isNewTestClass;
0208:            }
0209:
0210:            /**
0211:             */
0212:            public void run(WorkingCopy workingCopy) throws IOException {
0213:
0214:                workingCopy.toPhase(Phase.ELEMENTS_RESOLVED);
0215:
0216:                CompilationUnitTree compUnit = workingCopy.getCompilationUnit();
0217:                List<ClassTree> tstTopClasses = TopClassFinder.findTopClasses(
0218:                        compUnit, workingCopy.getTreeUtilities());
0219:                TreePath compUnitPath = new TreePath(compUnit);
0220:
0221:                List<TypeElement> srcTopClassElems = resolveHandles(
0222:                        workingCopy, srcTopClassElemHandles);
0223:
0224:                if ((srcTopClassElems != null) && !srcTopClassElems.isEmpty()) {
0225:
0226:                    final String className = workingCopy.getClasspathInfo()
0227:                            .getClassPath(ClasspathInfo.PathKind.SOURCE)
0228:                            .getResourceName(workingCopy.getFileObject(), '.',
0229:                                    false);
0230:
0231:                    /* Create/update a test class for each testable source class: */
0232:                    for (TypeElement srcTopClass : srcTopClassElems) {
0233:                        createOrUpdateTestClass(srcTopClass, tstTopClasses,
0234:                                className, compUnitPath, workingCopy);
0235:                    }
0236:                } else if (suiteMembers != null) { //test suite
0237:                    for (ClassTree tstClass : tstTopClasses) {
0238:                        TreePath tstClassTreePath = new TreePath(compUnitPath,
0239:                                tstClass);
0240:                        ClassTree origTstTopClass = tstClass;
0241:                        ClassTree tstTopClass = generateMissingSuiteClassMembers(
0242:                                tstClass, tstClassTreePath, suiteMembers,
0243:                                isNewTestClass, workingCopy);
0244:                        if (tstTopClass != origTstTopClass) {
0245:                            workingCopy.rewrite(origTstTopClass, tstTopClass);
0246:                        }
0247:                        classProcessed(tstClass);
0248:                    }
0249:                } else if (srcTopClassElems == null) { //new empty test class
0250:                    for (ClassTree tstClass : tstTopClasses) {
0251:                        ClassTree origTstTopClass = tstClass;
0252:                        ClassTree tstTopClass = generateMissingInitMembers(
0253:                                tstClass, new TreePath(compUnitPath, tstClass),
0254:                                workingCopy);
0255:                        if (tstTopClass != origTstTopClass) {
0256:                            workingCopy.rewrite(origTstTopClass, tstTopClass);
0257:                        }
0258:                    }
0259:                }
0260:            }
0261:
0262:            /**
0263:             * Creates or updates a test class for a given source class.
0264:             * 
0265:             * @param  srcTopClass  source class for which a test class should be
0266:             *                      created or updated
0267:             * @param  tstTopClasses  list of top-level classes that are present
0268:             *                        in the test source code
0269:             * @param  testClassName  desired name of the test class corresponding
0270:             *                        to the given source class; if a test class of the
0271:             *                        given name is not found, it is created
0272:             * @param  compUnitPath  tree-path to the compilation unit of the test
0273:             *                       source file
0274:             * @param  workingCopy  working copy of the test file's structure
0275:             */
0276:            private void createOrUpdateTestClass(TypeElement srcTopClass,
0277:                    List<ClassTree> tstTopClasses, String testClassName,
0278:                    TreePath compUnitPath, WorkingCopy workingCopy) {
0279:                List<ExecutableElement> srcMethods = findTestableMethods(srcTopClass);
0280:                boolean srcHasTestableMethods = !srcMethods.isEmpty();
0281:
0282:                final String testClassSimpleName = TestUtil
0283:                        .getSimpleName(testClassName);
0284:
0285:                /* Check whether the corresponding test class already exists: */
0286:                ClassTree tstTopClass = null;
0287:                for (ClassTree tstClass : tstTopClasses) {
0288:                    if (tstClass.getSimpleName().contentEquals(
0289:                            testClassSimpleName)) {
0290:                        tstTopClass = tstClass; //yes, it exists
0291:                        break;
0292:                    }
0293:                }
0294:
0295:                if (tstTopClass != null) { //if the test class already exists
0296:                    TreePath tstTopClassTreePath = new TreePath(compUnitPath,
0297:                            tstTopClass);
0298:
0299:                    ClassTree origTstTopClass = tstTopClass;
0300:                    if (srcHasTestableMethods) {
0301:                        tstTopClass = generateMissingTestMethods(srcTopClass,
0302:                                srcMethods, tstTopClass, tstTopClassTreePath,
0303:                                isNewTestClass, workingCopy);
0304:                    } else if (isNewTestClass) {
0305:                        tstTopClass = generateMissingInitMembers(tstTopClass,
0306:                                tstTopClassTreePath, workingCopy);
0307:                    }
0308:                    if (tstTopClass != origTstTopClass) {
0309:                        workingCopy.rewrite(origTstTopClass, tstTopClass);
0310:                    }
0311:                } else { //it does not exist - it must be created
0312:                    if (srcHasTestableMethods) {
0313:                        tstTopClass = generateNewTestClass(workingCopy,
0314:                                testClassSimpleName, srcTopClass, srcMethods);
0315:                        //PENDING - add the top class to the CompilationUnit
0316:
0317:                        //PENDING - generate suite method
0318:                    }
0319:                }
0320:            }
0321:
0322:            /**
0323:             * Generates a new test class for the given source class.
0324:             * 
0325:             * @param  name  name of the class to be created
0326:             * @param  srcClass  source class for which the test class should be created
0327:             * @param  srcMethods  methods inside the source class for which
0328:             *                     corresponding test methods should be created
0329:             * @return  generated test class
0330:             */
0331:            private ClassTree generateNewTestClass(WorkingCopy workingCopy,
0332:                    String name, TypeElement srcClass,
0333:                    List<ExecutableElement> srcMethods) {
0334:                List<MethodTree> testMethods = generateTestMethods(srcClass,
0335:                        srcMethods, workingCopy);
0336:                return composeNewTestClass(workingCopy, name, testMethods);
0337:            }
0338:
0339:            /**
0340:             * Generates a new test class containing the given list of test methods.
0341:             * 
0342:             * @param  name  desired name of the test class
0343:             * @param  members  desired content of the test class
0344:             * @return  generated test class
0345:             */
0346:            protected abstract ClassTree composeNewTestClass(
0347:                    WorkingCopy workingCopy, String name,
0348:                    List<? extends Tree> members);
0349:
0350:            /**
0351:             */
0352:            protected abstract List<? extends Tree> generateInitMembers(
0353:                    WorkingCopy workingCopy);
0354:
0355:            /**
0356:             * Generates missing set-up and tear-down methods in the given test class.
0357:             * 
0358:             * @param  tstClass  test class in which the methods should be generated
0359:             * @return  a class tree with the missing methods added;
0360:             *          or the passed class tree if no method was missing
0361:             */
0362:            protected abstract ClassTree generateMissingInitMembers(
0363:                    ClassTree tstClass, TreePath tstClassTreePath,
0364:                    WorkingCopy workingCopy);
0365:
0366:            /**
0367:             * Generates missing set-up and tear-down methods and adds them to the list
0368:             * of class members.
0369:             * 
0370:             * @param  tstMembers  current list of test class members
0371:             *                     - generated members will be added to it
0372:             * @param  clsMap  index of the test class contents
0373:             *                 - it will be updated if some members are added
0374:             *                 to the list
0375:             * @return  {@code true} if the list of members was modified,
0376:             *          {@code false} otherwise
0377:             */
0378:            protected abstract boolean generateMissingInitMembers(
0379:                    List<Tree> tstMembers, ClassMap clsMap,
0380:                    WorkingCopy workingCopy);
0381:
0382:            /**
0383:             * Finds position for the first init method.
0384:             * 
0385:             * @param  clsMap  index of the test class contents
0386:             * @return  index where the first init method should be put,
0387:             *          or {@code -1} if the method should be put to the end
0388:             *          of the class
0389:             */
0390:            protected int getPlaceForFirstInitMethod(ClassMap clsMap) {
0391:                int targetIndex;
0392:                if (clsMap.containsMethods()) {
0393:                    targetIndex = clsMap.getFirstMethodIndex();
0394:                } else if (clsMap.containsInitializers()) {
0395:                    targetIndex = clsMap.getLastInitializerIndex() + 1;
0396:                } else if (clsMap.containsNestedClasses()) {
0397:                    targetIndex = clsMap.getFirstNestedClassIndex();
0398:                } else {
0399:                    targetIndex = -1; //end of the class
0400:                }
0401:                return targetIndex;
0402:            }
0403:
0404:            /**
0405:             * 
0406:             * @param  srcMethods  methods to create/update tests for
0407:             * 
0408:             */
0409:            protected ClassTree generateMissingTestMethods(
0410:                    TypeElement srcClass, List<ExecutableElement> srcMethods,
0411:                    ClassTree tstClass, TreePath tstClassTreePath,
0412:                    boolean generateMissingInitMembers, WorkingCopy workingCopy) {
0413:                if (srcMethods.isEmpty()) {
0414:                    return tstClass;
0415:                }
0416:
0417:                ClassMap clsMap = ClassMap.forClass(tstClass, tstClassTreePath,
0418:                        workingCopy.getTrees());
0419:
0420:                List<? extends Tree> tstMembersOrig = tstClass.getMembers();
0421:                List<Tree> tstMembers = new ArrayList<Tree>(tstMembersOrig
0422:                        .size() + 4);
0423:                tstMembers.addAll(tstMembersOrig);
0424:
0425:                if (generateMissingInitMembers) {
0426:                    generateMissingInitMembers(tstMembers, clsMap, workingCopy);
0427:                }
0428:                generateMissingPostInitMethods(tstClassTreePath, tstMembers,
0429:                        clsMap, workingCopy);
0430:
0431:                /* Generate test method names: */
0432:                TypeElement tstClassElem = (TypeElement) workingCopy.getTrees()
0433:                        .getElement(tstClassTreePath);
0434:                List<String> testMethodNames = TestMethodNameGenerator
0435:                        .getTestMethodNames(srcMethods, tstClassElem, clsMap
0436:                                .getNoArgMethods(), workingCopy);
0437:
0438:                Iterator<ExecutableElement> srcMethodsIt = srcMethods
0439:                        .iterator();
0440:                Iterator<String> tstMethodNamesIt = testMethodNames.iterator();
0441:
0442:                Boolean useNoArgConstrutor = null;
0443:                while (srcMethodsIt.hasNext()) {
0444:                    assert tstMethodNamesIt.hasNext();
0445:
0446:                    ExecutableElement srcMethod = srcMethodsIt.next();
0447:                    String testMethodName = tstMethodNamesIt.next();
0448:                    int testMethodIndex = clsMap
0449:                            .findNoArgMethod(testMethodName);
0450:                    if (testMethodIndex != -1) {
0451:                        continue; //corresponding test method already exists
0452:                    }
0453:
0454:                    if (useNoArgConstrutor == null) {
0455:                        useNoArgConstrutor = Boolean
0456:                                .valueOf(hasAccessibleNoArgConstructor(srcClass));
0457:                    }
0458:                    MethodTree newTestMethod = generateTestMethod(srcClass,
0459:                            srcMethod, testMethodName, useNoArgConstrutor
0460:                                    .booleanValue(), workingCopy);
0461:
0462:                    tstMembers.add(newTestMethod);
0463:                    clsMap.addNoArgMethod(newTestMethod.getName().toString());
0464:                }
0465:                assert !tstMethodNamesIt.hasNext();
0466:
0467:                if (tstMembers.size() == tstMembersOrig.size()) { //no test method added
0468:                    return tstClass;
0469:                }
0470:
0471:                ClassTree newClass = workingCopy.getTreeMaker().Class(
0472:                        tstClass.getModifiers(),
0473:                        tstClass.getSimpleName(),
0474:                        tstClass.getTypeParameters(),
0475:                        tstClass.getExtendsClause(),
0476:                        (List<? extends ExpressionTree>) tstClass
0477:                                .getImplementsClause(), tstMembers);
0478:                return newClass;
0479:            }
0480:
0481:            /**
0482:             */
0483:            protected abstract void generateMissingPostInitMethods(
0484:                    TreePath tstClassTreePath, List<Tree> tstMembers,
0485:                    ClassMap clsMap, WorkingCopy workingCopy);
0486:
0487:            /**
0488:             * Generates test methods for the given source methods.
0489:             * The created test methods will be put to a newly created test class.
0490:             * The test class does not exist at the moment this method is called.
0491:             * 
0492:             * @param  srcClass  source class containing the source methods
0493:             * @param  srcMethods  source methods the test methods should be created for
0494:             */
0495:            private List<MethodTree> generateTestMethods(TypeElement srcClass,
0496:                    List<ExecutableElement> srcMethods, WorkingCopy workingCopy) {
0497:                if (srcMethods.isEmpty()) {
0498:                    return Collections.<MethodTree> emptyList();
0499:                }
0500:
0501:                List<String> testMethodNames = TestMethodNameGenerator
0502:                        .getTestMethodNames(srcMethods, null, null, //reserved
0503:                                workingCopy);
0504:
0505:                Iterator<ExecutableElement> srcMethodsIt = srcMethods
0506:                        .iterator();
0507:                Iterator<String> tstMethodNamesIt = testMethodNames.iterator();
0508:
0509:                boolean useNoArgConstrutor = hasAccessibleNoArgConstructor(srcClass);
0510:                List<MethodTree> testMethods = new ArrayList<MethodTree>(
0511:                        srcMethods.size());
0512:                while (srcMethodsIt.hasNext()) {
0513:                    assert tstMethodNamesIt.hasNext();
0514:
0515:                    ExecutableElement srcMethod = srcMethodsIt.next();
0516:                    String testMethodName = tstMethodNamesIt.next();
0517:
0518:                    testMethods.add(generateTestMethod(srcClass, srcMethod,
0519:                            testMethodName, useNoArgConstrutor, workingCopy));
0520:                }
0521:                assert !tstMethodNamesIt.hasNext();
0522:                return testMethods;
0523:            }
0524:
0525:            /**
0526:             * Generates a test methods for the given source method.
0527:             * 
0528:             * @param  srcClass  source class - parent of the source method
0529:             * @param  srcMethod  source method for which the test method should be
0530:             *                    created
0531:             * @param  useNoArgConstrutor  whether a no-argument constructor should be
0532:             *                             used in the default test method body;
0533:             *                             it should not be {@code true} unless
0534:             *                             the source class contains an accessible
0535:             *                             no-argument constructor
0536:             * @return  the generated test method
0537:             */
0538:            protected MethodTree generateTestMethod(TypeElement srcClass,
0539:                    ExecutableElement srcMethod, String testMethodName,
0540:                    boolean useNoArgConstructor, WorkingCopy workingCopy) {
0541:                final TreeMaker maker = workingCopy.getTreeMaker();
0542:
0543:                List<ExpressionTree> throwsList;
0544:                if (throwsNonRuntimeExceptions(workingCopy, srcMethod)) {
0545:                    throwsList = Collections
0546:                            .<ExpressionTree> singletonList(maker
0547:                                    .Identifier("Exception")); //NOI18N
0548:                } else {
0549:                    throwsList = Collections.<ExpressionTree> emptyList();
0550:                }
0551:
0552:                MethodTree method = composeNewTestMethod(testMethodName,
0553:                        generateTestMethodBody(srcClass, srcMethod,
0554:                                useNoArgConstructor, workingCopy), throwsList,
0555:                        workingCopy);
0556:
0557:                if (setup.isGenerateMethodJavadoc()) {
0558:                    String commentText = NbBundle.getMessage(TestCreator.class,
0559:                            "TestCreator.variantMethods.JavaDoc.comment", //NOI18N
0560:                            srcMethod.getSimpleName().toString(), srcClass
0561:                                    .getSimpleName().toString());
0562:                    Comment javadoc = Comment.create(Comment.Style.JAVADOC, -2,
0563:                            -2, -2, commentText);
0564:                    maker.addComment(method, javadoc, true);
0565:                }
0566:
0567:                return method;
0568:            }
0569:
0570:            /**
0571:             */
0572:            protected abstract MethodTree composeNewTestMethod(
0573:                    String testMethodName, BlockTree testMethodBody,
0574:                    List<ExpressionTree> throwsList, WorkingCopy workingCopy);
0575:
0576:            /**
0577:             */
0578:            private ClassTree generateMissingSuiteClassMembers(
0579:                    ClassTree tstClass, TreePath tstClassTreePath,
0580:                    List<String> suiteMembers, boolean isNewTestClass,
0581:                    WorkingCopy workingCopy) {
0582:                final TreeMaker maker = workingCopy.getTreeMaker();
0583:
0584:                List<? extends Tree> tstMembersOrig = tstClass.getMembers();
0585:                List<Tree> tstMembers = new ArrayList<Tree>(tstMembersOrig
0586:                        .size() + 2);
0587:                tstMembers.addAll(tstMembersOrig);
0588:                boolean membersChanged = false;
0589:
0590:                ClassMap classMap = ClassMap.forClass(tstClass,
0591:                        tstClassTreePath, workingCopy.getTrees());
0592:
0593:                if (isNewTestClass) {
0594:                    membersChanged |= generateMissingInitMembers(tstMembers,
0595:                            classMap, workingCopy);
0596:                }
0597:
0598:                return finishSuiteClass(tstClass, tstClassTreePath, tstMembers,
0599:                        suiteMembers, membersChanged, classMap, workingCopy);
0600:            }
0601:
0602:            /**
0603:             */
0604:            protected abstract ClassTree finishSuiteClass(ClassTree tstClass,
0605:                    TreePath tstClassTreePath, List<Tree> tstMembers,
0606:                    List<String> suiteMembers, boolean membersChanged,
0607:                    ClassMap classMap, WorkingCopy workingCopy);
0608:
0609:            // <editor-fold defaultstate="collapsed" desc=" disabled code ">
0610:            //        /**
0611:            //         */
0612:            //        private void addMainMethod(final ClassTree classTree) {
0613:            //            MethodTree mainMethod = createMainMethod(maker);
0614:            //            if (mainMethod != null) {
0615:            //                maker.addClassMember(classTree, mainMethod);
0616:            //            }
0617:            //        }
0618:            //
0619:            //        /**
0620:            //         */
0621:            //        private void fillTestClass(JavaClass srcClass, JavaClass tstClass) {
0622:            //            
0623:            //            fillGeneral(tstClass);
0624:            //
0625:            //            List innerClasses = TestUtil.filterFeatures(srcClass,
0626:            //                                                        JavaClass.class);
0627:            //
0628:            //            /* Create test classes for inner classes: */
0629:            //            for (Iterator i = innerClasses.iterator(); i.hasNext(); ) {
0630:            //                JavaClass innerCls = (JavaClass) i.next();
0631:            //
0632:            //                if (!isClassTestable(innerCls).isTestable()) {
0633:            //                    continue;
0634:            //                }
0635:            //                    
0636:            //                /*
0637:            //                 * Check whether the test class for the inner class exists
0638:            //                 * and create one if it does not exist:
0639:            //                 */
0640:            //                String innerTestClsName
0641:            //                        = TestUtil.getTestClassName(innerCls.getSimpleName());
0642:            //                JavaClass innerTestCls
0643:            //                        = TestUtil.getClassBySimpleName(tstClass,
0644:            //                                                        innerTestClsName);
0645:            //                if (innerTestCls == null) {
0646:            //                    innerTestCls = tgtPkg.getJavaClass().createJavaClass();
0647:            //                    innerTestCls.setSimpleName(
0648:            //                            tstClass.getName() + '.' + innerTestClsName);
0649:            //                    tstClass.getFeatures().add(innerTestCls);
0650:            //                }
0651:            //
0652:            //                /* Process the tested inner class: */
0653:            //                fillTestClass(innerCls, innerTestCls);
0654:            //
0655:            //                /* Make the inner test class testable with JUnit: */
0656:            //                innerTestCls.setModifiers(innerTestCls.getModifiers() | Modifier.STATIC);
0657:            //            }
0658:            //
0659:            //            /* Add the suite() method (only if we are supposed to do so): */
0660:            //            if (generateSuiteClasses && !hasSuiteMethod(tstClass)) {
0661:            //                tstClass.getFeatures().add(createTestClassSuiteMethod(tstClass));
0662:            //            }
0663:            //
0664:            //            /* Create missing test methods: */
0665:            //            List srcMethods = TestUtil.filterFeatures(srcClass, Method.class);
0666:            //            for (Iterator i = srcMethods.iterator(); i.hasNext(); ) {
0667:            //                Method sm = (Method) i.next();
0668:            //                if (isMethodAcceptable(sm) &&
0669:            //                        tstClass.getMethod(createTestMethodName(sm.getName()),
0670:            //                                          Collections.EMPTY_LIST,
0671:            //                                          false)
0672:            //                        == null) {
0673:            //                    Method tm = createTestMethod(srcClass, sm);
0674:            //                    tstClass.getFeatures().add(tm);
0675:            //                }
0676:            //            }
0677:            //
0678:            //            /* Create abstract class implementation: */
0679:            //            if (!skipAbstractClasses
0680:            //                    && (Modifier.isAbstract(srcClass.getModifiers())
0681:            //                        || srcClass.isInterface())) {
0682:            //                createAbstractImpl(srcClass, tstClass);
0683:            //            }
0684:            //        }
0685:            // </editor-fold>
0686:
0687:            // <editor-fold defaultstate="collapsed" desc=" disabled code ">
0688:            //        /**
0689:            //         */
0690:            //        private Constructor createTestConstructor(String className) {
0691:            //            Constructor constr = tgtPkg.getConstructor().createConstructor(
0692:            //                               className,               // name
0693:            //                               Collections.EMPTY_LIST,  // annotations
0694:            //                               Modifier.PUBLIC,         // modifiers
0695:            //                               null,                    // Javadoc text
0696:            //                               null,                    // Javadoc - object
0697:            //                               null,                    // body - object
0698:            //                               "super(testName);\n",    // body - text  //NOI18N
0699:            //                               Collections.EMPTY_LIST,  // type parameters
0700:            //                               createTestConstructorParams(),  // parameters
0701:            //                               null);                   // exception names
0702:            //            return constr;
0703:            //        }
0704:            //
0705:            //        /**
0706:            //         */
0707:            //        private List/*<Parameter>*/ createTestConstructorParams() {
0708:            //            Parameter param = tgtPkg.getParameter().createParameter(
0709:            //                                "testName",             // parameter name
0710:            //                                Collections.EMPTY_LIST, // annotations
0711:            //                                false,                  // not final
0712:            //                                TestUtil.getTypeReference(   // type
0713:            //                                        tgtPkg, "String"),              //NOI18N
0714:            //                                0,                      // dimCount
0715:            //                                false);                 // is not var.arg.
0716:            //            return Collections.singletonList(param);
0717:            //        }
0718:            // </editor-fold>
0719:
0720:            /**
0721:             * Creates a public static {@code main(String[])} method
0722:             * with the body taken from settings.
0723:             *
0724:             * @param  maker  {@code TreeMaker} to use for creating the method
0725:             * @return  created {@code main(...)} method,
0726:             *          or {@code null} if the method body would be empty
0727:             */
0728:            private MethodTree createMainMethod(TreeMaker maker) {
0729:                String initialMainMethodBody = getInitialMainMethodBody();
0730:                if (initialMainMethodBody.length() == 0) {
0731:                    return null;
0732:                }
0733:
0734:                ModifiersTree modifiers = maker.Modifiers(createModifierSet(
0735:                        Modifier.PUBLIC, Modifier.STATIC));
0736:                VariableTree param = maker.Variable(maker.Modifiers(Collections
0737:                        .<Modifier> emptySet()), "argList", //NOI18N
0738:                        maker.Identifier("String[]"), //NOI18N
0739:                        null); //initializer - not used in params
0740:                MethodTree mainMethod = maker.Method(modifiers, //public static
0741:                        "main", //method name "main"//NOI18N
0742:                        maker.PrimitiveType(TypeKind.VOID), //return type "void"
0743:                        Collections.<TypeParameterTree> emptyList(), //type params
0744:                        Collections.<VariableTree> singletonList(param), //method param
0745:                        Collections.<ExpressionTree> emptyList(), //throws-list
0746:                        '{' + initialMainMethodBody + '}', //body text
0747:                        null); //only for annotations
0748:
0749:                return mainMethod;
0750:            }
0751:
0752:            // <editor-fold defaultstate="collapsed" desc=" disabled code ">
0753:            //        /**
0754:            //         */
0755:            //        private void createAbstractImpl(JavaClass srcClass,
0756:            //                                        JavaClass tstClass) {
0757:            //            String implClassName = srcClass.getSimpleName() + "Impl";   //NOI18N
0758:            //            JavaClass innerClass = tstClass.getInnerClass(implClassName, false);
0759:            //
0760:            //            if (innerClass == null) {
0761:            //                String javadocText = 
0762:            //                        generateMethodJavadoc
0763:            //                        ? javadocText = NbBundle.getMessage(
0764:            //                              TestCreator.class,
0765:            //                              "TestCreator.abstracImpl.JavaDoc.comment",//NOI18N
0766:            //                              srcClass.getName())
0767:            //                        : null;
0768:            //
0769:            //                // superclass
0770:            //                MultipartId supClass
0771:            //                        = tgtPkg.getMultipartId().createMultipartId(
0772:            //                                srcClass.isInner() ? srcClass.getName()
0773:            //                                                   : srcClass.getSimpleName(),
0774:            //                                null,
0775:            //                                Collections.EMPTY_LIST);
0776:            //
0777:            //                innerClass = tgtPkg.getJavaClass().createJavaClass(
0778:            //                                implClassName,          // class name
0779:            //                                Collections.EMPTY_LIST, // annotations
0780:            //                                Modifier.PRIVATE,       // modifiers
0781:            //                                javadocText,            // Javadoc text
0782:            //                                null,                   // Javadoc - object
0783:            //                                Collections.EMPTY_LIST, // contents
0784:            //                                null,                   // super class name
0785:            //                                Collections.EMPTY_LIST, // interface names
0786:            //                                Collections.EMPTY_LIST);// type parameters
0787:            //                
0788:            //                if (srcClass.isInterface()) {
0789:            //                    innerClass.getInterfaceNames().add(supClass);
0790:            //                } else {
0791:            //                    innerClass.setSuperClassName(supClass);
0792:            //                }
0793:            //
0794:            //                createImpleConstructors(srcClass, innerClass);
0795:            //                tstClass.getFeatures().add(innerClass);
0796:            //            }
0797:            //
0798:            //            // created dummy implementation for all abstract methods
0799:            //            List abstractMethods = TestUtil.collectFeatures(
0800:            //                                            srcClass,
0801:            //                                            Method.class,
0802:            //                                            Modifier.ABSTRACT,
0803:            //                                            true);
0804:            //            for (Iterator i = abstractMethods.iterator(); i.hasNext(); ) {
0805:            //                Method oldMethod = (Method) i.next();
0806:            //                if (innerClass.getMethod(
0807:            //                        oldMethod.getName(),
0808:            //                        TestUtil.getParameterTypes(oldMethod.getParameters()),
0809:            //                        false) == null) {
0810:            //                    Method newMethod = createMethodImpl(oldMethod);
0811:            //                    innerClass.getFeatures().add(newMethod);
0812:            //                }
0813:            //
0814:            //            }
0815:            //        }
0816:            //
0817:            //        /**
0818:            //         */
0819:            //        private void createImpleConstructors(JavaClass srcClass,
0820:            //                                             JavaClass tgtClass) {
0821:            //            List constructors = TestUtil.filterFeatures(srcClass,
0822:            //                                                        Constructor.class);
0823:            //            for (Iterator i = constructors.iterator(); i.hasNext(); ) {
0824:            //                Constructor ctr = (Constructor) i.next();
0825:            //                
0826:            //                if (Modifier.isPrivate(ctr.getModifiers())) {
0827:            //                    continue;
0828:            //                }
0829:            //                
0830:            //                Constructor nctr = tgtPkg.getConstructor().createConstructor();
0831:            //                nctr.setBodyText("super("                               //NOI18N
0832:            //                                 + getParameterString(ctr.getParameters())
0833:            //                                 + ");\n");                             //NOI18N
0834:            //                nctr.getParameters().addAll(
0835:            //                        TestUtil.cloneParams(ctr.getParameters(), tgtPkg));
0836:            //                tgtClass.getFeatures().add(nctr);
0837:            //            }
0838:            //        }
0839:            //
0840:            //        /**
0841:            //         */
0842:            //        private Method createMethodImpl(Method origMethod)  {
0843:            //            Method  newMethod = tgtPkg.getMethod().createMethod();
0844:            //
0845:            //            newMethod.setName(origMethod.getName());
0846:            //
0847:            //            /* Set modifiers of the method: */
0848:            //            int mod = origMethod.getModifiers() & ~Modifier.ABSTRACT;
0849:            //            if (((JavaClass) origMethod.getDeclaringClass()).isInterface()) {
0850:            //                mod |= Modifier.PUBLIC;
0851:            //            }
0852:            //            newMethod.setModifiers(mod);
0853:            //
0854:            //            // prepare the body of method implementation
0855:            //            StringBuffer    body = new StringBuffer(200);
0856:            //            if (generateSourceCodeHints) {
0857:            //                body.append(NbBundle.getMessage(
0858:            //                        TestCreator.class,
0859:            //                        "TestCreator.methodImpl.bodyComment"));         //NOI18N
0860:            //                body.append("\n\n");                                    //NOI18N
0861:            //            }
0862:            //
0863:            //            newMethod.setType(origMethod.getType());
0864:            //            Type type = origMethod.getType();
0865:            //            if (type != null) {
0866:            //                String value = null;
0867:            //                if ((type instanceof JavaClass) || (type instanceof Array)) {
0868:            //                    value = "null";                                     //NOI18N
0869:            //                } else if (type instanceof PrimitiveType) {
0870:            //                    PrimitiveTypeKindEnum tke = (PrimitiveTypeKindEnum)
0871:            //                                               ((PrimitiveType) type).getKind();
0872:            //                    if (tke.equals(PrimitiveTypeKindEnum.BOOLEAN)) {
0873:            //                        value = "false";                                //NOI18N
0874:            //                    } else if (!tke.equals(PrimitiveTypeKindEnum.VOID)) {
0875:            //                        value = "0";                                    //NOI18N
0876:            //                    }
0877:            //                }
0878:            //
0879:            //                if (value != null) {
0880:            //                    body.append("return ").append(value).append(";\n"); //NOI18N
0881:            //                }
0882:            //            }
0883:            //
0884:            //            newMethod.setBodyText(body.toString());
0885:            //
0886:            //            // parameters
0887:            //            newMethod.getParameters().addAll(
0888:            //                    TestUtil.cloneParams(origMethod.getParameters(), tgtPkg));
0889:            //
0890:            //            return newMethod;
0891:            //        }
0892:            //
0893:            //        /**
0894:            //         */
0895:            //        private String generateJavadoc(JavaClass srcClass, Method srcMethod) {
0896:            //            return NbBundle.getMessage(
0897:            //                        TestCreator.class,
0898:            //                        "TestCreator.variantMethods.JavaDoc.comment",   //NOI18N
0899:            //                        srcMethod.getName(),
0900:            //                        srcClass.getName());
0901:            //        }
0902:            // </editor-fold>
0903:
0904:            /**
0905:             * Generates a default body of a test method.
0906:             * 
0907:             * @param  srcClass  class - parent of the tested source method
0908:             * @param  srcMethod  source method which should be tested by the test
0909:             * @param  useNoArgConstrutor  whether a no-argument constructor should be
0910:             *                             used in the body;
0911:             *                             it should not be {@code true} unless
0912:             *                             the source class contains an accessible
0913:             *                             no-argument constructor
0914:             */
0915:            protected BlockTree generateTestMethodBody(TypeElement srcClass,
0916:                    ExecutableElement srcMethod, boolean useNoArgConstructor,
0917:                    WorkingCopy workingCopy) {
0918:                TreeMaker maker = workingCopy.getTreeMaker();
0919:
0920:                boolean isStatic = srcMethod.getModifiers().contains(
0921:                        Modifier.STATIC);
0922:                List<StatementTree> statements = new ArrayList<StatementTree>(8);
0923:
0924:                if (setup.isGenerateDefMethodBody()) {
0925:                    StatementTree sout = generateSystemOutPrintln(maker,
0926:                            srcMethod.getSimpleName().toString());
0927:                    List<VariableTree> paramVariables = generateParamVariables(
0928:                            maker, srcMethod);
0929:                    statements.add(sout);
0930:                    statements.addAll(paramVariables);
0931:
0932:                    if (!isStatic) {
0933:                        VariableTree instanceVarInit = maker
0934:                                .Variable(
0935:                                        maker.Modifiers(Collections
0936:                                                .<Modifier> emptySet()),
0937:                                        INSTANCE_VAR_NAME,
0938:                                        maker.QualIdent(srcClass),
0939:                                        useNoArgConstructor ? generateNoArgConstructorCall(
0940:                                                maker, srcClass)
0941:                                                : maker.Literal(null));
0942:                        statements.add(instanceVarInit);
0943:                    }
0944:
0945:                    MethodInvocationTree methodCall = maker.MethodInvocation(
0946:                            Collections.<ExpressionTree> emptyList(), //type args.
0947:                            maker.MemberSelect(isStatic ? maker
0948:                                    .QualIdent(srcClass) : maker
0949:                                    .Identifier(INSTANCE_VAR_NAME), srcMethod
0950:                                    .getSimpleName()), createIdentifiers(maker,
0951:                                    paramVariables));
0952:
0953:                    TypeMirror retType = srcMethod.getReturnType();
0954:                    TypeKind retTypeKind = retType.getKind();
0955:
0956:                    if ((retTypeKind == TypeKind.VOID)
0957:                            || (retTypeKind == TypeKind.ERROR)) {
0958:                        StatementTree methodCallStmt = maker
0959:                                .ExpressionStatement(methodCall);
0960:
0961:                        statements.add(methodCallStmt);
0962:                    } else {
0963:                        Tree retTypeTree = maker.Type(retType);
0964:
0965:                        VariableTree expectedValue = maker.Variable(maker
0966:                                .Modifiers(NO_MODIFIERS), EXP_RESULT_VAR_NAME,
0967:                                retTypeTree, getDefaultValue(maker, retType));
0968:                        VariableTree actualValue = maker.Variable(maker
0969:                                .Modifiers(NO_MODIFIERS), RESULT_VAR_NAME,
0970:                                retTypeTree, methodCall);
0971:
0972:                        List<ExpressionTree> comparisonArgs = new ArrayList<ExpressionTree>(
0973:                                2);
0974:                        comparisonArgs.add(maker.Identifier(expectedValue
0975:                                .getName().toString()));
0976:                        comparisonArgs.add(maker.Identifier(actualValue
0977:                                .getName().toString()));
0978:
0979:                        MethodInvocationTree comparison = maker
0980:                                .MethodInvocation(Collections
0981:                                        .<ExpressionTree> emptyList(), //type args.
0982:                                        maker.Identifier("assertEquals"), //NOI18N
0983:                                        comparisonArgs);
0984:                        StatementTree comparisonStmt = maker
0985:                                .ExpressionStatement(comparison);
0986:
0987:                        statements.add(expectedValue);
0988:                        statements.add(actualValue);
0989:                        statements.add(comparisonStmt);
0990:                    }
0991:                }
0992:
0993:                //PENDING - source code hints
0994:                //            if (generateSourceCodeHints) {
0995:                //                // generate comments to bodies
0996:                //                if (needsEmptyLine) {
0997:                //                    newBody.append('\n');
0998:                //                    needsEmptyLine = false;
0999:                //                }
1000:                //                newBody.append(NbBundle.getMessage(
1001:                //                    TestCreator.class,
1002:                //                    generateDefMethodBody
1003:                //                           ? "TestCreator.variantMethods.defaultComment"//NOI18N
1004:                //                           : "TestCreator.variantMethods.onlyComment")) //NOI18N
1005:                //                       .append('\n');
1006:                //            }
1007:
1008:                if (setup.isGenerateDefMethodBody()) {
1009:                    String failMsg = NbBundle.getMessage(TestCreator.class,
1010:                            "TestCreator.variantMethods.defaultFailMsg"); //NOI18N
1011:                    MethodInvocationTree failMethodCall = maker
1012:                            .MethodInvocation(
1013:                                    Collections.<ExpressionTree> emptyList(), //type args.
1014:                                    maker.Identifier("fail"), //NOI18N
1015:                                    Collections
1016:                                            .<ExpressionTree> singletonList(maker
1017:                                                    .Literal(failMsg)));
1018:
1019:                    ExpressionStatementTree exprStatement = maker
1020:                            .ExpressionStatement(failMethodCall);
1021:                    if (setup.isGenerateMethodBodyComment()) {
1022:                        Comment comment = Comment
1023:                                .create(
1024:                                        Comment.Style.LINE,
1025:                                        -2,
1026:                                        -2,
1027:                                        -2,
1028:                                        NbBundle
1029:                                                .getMessage(
1030:                                                        AbstractTestGenerator.class,
1031:                                                        "TestCreator.variantMethods.defaultComment"));//NOI18N
1032:                        maker.addComment(exprStatement, comment, true);
1033:                    }
1034:                    statements.add(exprStatement);
1035:                }
1036:
1037:                return maker.Block(statements, false);
1038:            }
1039:
1040:            /**
1041:             */
1042:            private StatementTree generateSystemOutPrintln(TreeMaker maker,
1043:                    String arg) {
1044:                MethodInvocationTree methodInvocation = maker.MethodInvocation(
1045:                        Collections.<ExpressionTree> emptyList(), //type args
1046:                        maker.MemberSelect(maker.MemberSelect(maker
1047:                                .Identifier("System"), "out"), "println"),//NOI18N
1048:                        Collections.<LiteralTree> singletonList(maker
1049:                                .Literal(arg))); //args.
1050:                return maker.ExpressionStatement(methodInvocation);
1051:            }
1052:
1053:            /**
1054:             */
1055:            private List<VariableTree> generateParamVariables(TreeMaker maker,
1056:                    ExecutableElement srcMethod) {
1057:                List<? extends VariableElement> params = srcMethod
1058:                        .getParameters();
1059:                if ((params == null) || params.isEmpty()) {
1060:                    return Collections.<VariableTree> emptyList();
1061:                }
1062:
1063:                Set<Modifier> noModifiers = Collections.<Modifier> emptySet();
1064:                List<VariableTree> paramVariables = new ArrayList<VariableTree>(
1065:                        params.size());
1066:                String[] varNames = getTestSkeletonVarNames(params);
1067:                int index = 0;
1068:                for (VariableElement param : params) {
1069:                    TypeMirror paramType = param.asType();
1070:                    paramVariables.add(maker
1071:                            .Variable(maker.Modifiers(noModifiers),
1072:                                    varNames[index++], maker.Type(paramType),
1073:                                    getDefaultValue(maker, paramType)));
1074:                }
1075:                return paramVariables;
1076:            }
1077:
1078:            /**
1079:             */
1080:            private List<IdentifierTree> createIdentifiers(TreeMaker maker,
1081:                    List<VariableTree> variables) {
1082:                List<IdentifierTree> identifiers;
1083:                if (variables.isEmpty()) {
1084:                    identifiers = Collections.<IdentifierTree> emptyList();
1085:                } else {
1086:                    identifiers = new ArrayList<IdentifierTree>(variables
1087:                            .size());
1088:                    for (VariableTree var : variables) {
1089:                        identifiers.add(maker.Identifier(var.getName()
1090:                                .toString()));
1091:                    }
1092:                }
1093:                return identifiers;
1094:            }
1095:
1096:            /**
1097:             * Builds list of variable names for use in a test method skeleton.
1098:             * By default, names of variables are same as names of tested method's
1099:             * declared parameters. There are three variable names reserved
1100:             * for variables holding the instance the tested method will be called on,
1101:             * the expected result and the actual result returned
1102:             * by the tested method. This method resolves a potential conflict
1103:             * if some of the tested method's parameter's name is one of these
1104:             * reserved names - in this case, the variable name used is a slight
1105:             * modification of the declared parameter's name. The method also resolves
1106:             * cases that some or all parameters are without name - in this case,
1107:             * an arbitrary name is assigned to each of these unnamed parameters.
1108:             * The goal is to ensure that all of the used variable names are unique.
1109:             *
1110:             * @param  sourceMethodParams 
1111:             *                  list of tested method's parameters (items are of type
1112:             *                  <code>org.netbeans.jmi.javamodel.TypeParameter</code>)
1113:             * @return  variable names used for default values of the tested method's
1114:             *          parameters (the reserved variable names are not included)
1115:             */
1116:            private String[] getTestSkeletonVarNames(
1117:                    final List<? extends VariableElement> sourceMethodParams) {
1118:
1119:                /* Handle the trivial case: */
1120:                if (sourceMethodParams.isEmpty()) {
1121:                    return new String[0];
1122:                }
1123:
1124:                final int count = sourceMethodParams.size();
1125:                String[] varNames = new String[count];
1126:                boolean[] conflicts = new boolean[count];
1127:                boolean issueFound = false;
1128:
1129:                Set<String> varNamesSet = new HashSet<String>(
1130:                        (int) ((count + 2) * 1.4));
1131:                varNamesSet.add(INSTANCE_VAR_NAME);
1132:                varNamesSet.add(RESULT_VAR_NAME);
1133:                varNamesSet.add(EXP_RESULT_VAR_NAME);
1134:
1135:                Iterator<? extends VariableElement> it = sourceMethodParams
1136:                        .iterator();
1137:                for (int i = 0; i < count; i++) {
1138:                    String paramName = it.next().getSimpleName().toString();
1139:                    varNames[i] = paramName;
1140:
1141:                    if (paramName == null) {
1142:                        issueFound = true;
1143:                    } else if (!varNamesSet.add(paramName)) {
1144:                        conflicts[i] = true;
1145:                        issueFound = true;
1146:                    } else {
1147:                        conflicts[i] = false;
1148:                    }
1149:                }
1150:
1151:                if (issueFound) {
1152:                    for (int i = 0; i < count; i++) {
1153:                        String paramName;
1154:                        if (varNames[i] == null) {
1155:                            paramName = ARTIFICAL_VAR_NAME_BASE + i;
1156:                            if (varNamesSet.add(paramName)) {
1157:                                varNames[i] = paramName;
1158:                                continue;
1159:                            } else {
1160:                                conflicts[i] = true;
1161:                            }
1162:                        }
1163:                        if (conflicts[i]) {
1164:                            String paramNamePrefix = varNames[i] + '_';
1165:
1166:                            int index = 2;
1167:                            while (!varNamesSet
1168:                                    .add(paramName = (paramNamePrefix + (index++))))
1169:                                ;
1170:                            varNames[i] = paramName;
1171:                        }
1172:                    }
1173:                }
1174:
1175:                return varNames;
1176:            }
1177:
1178:            /**
1179:             */
1180:            private ExpressionTree getDefaultValue(TreeMaker maker,
1181:                    TypeMirror type) {
1182:                ExpressionTree defValue;
1183:                TypeKind typeKind = type.getKind();
1184:                if (typeKind.isPrimitive()) {
1185:                    switch (typeKind) {
1186:                    case BOOLEAN:
1187:                        defValue = maker.Literal(Boolean.FALSE);
1188:                        break;
1189:                    case CHAR:
1190:                        defValue = maker.Literal(new Character(' '));
1191:                        break;
1192:                    case BYTE:
1193:                        defValue = maker.Literal(new Byte((byte) 0));
1194:                        break;
1195:                    case SHORT:
1196:                        defValue = maker.Literal(new Short((short) 0));
1197:                        break;
1198:                    case INT:
1199:                        defValue = maker.Literal(new Integer(0));
1200:                        break;
1201:                    case FLOAT:
1202:                        defValue = maker.Literal(new Float(0.0F));
1203:                        break;
1204:                    case LONG:
1205:                        defValue = maker.Literal(new Long(0L));
1206:                        break;
1207:                    case DOUBLE:
1208:                        defValue = maker.Literal(new Double(0.0));
1209:                        break;
1210:                    default:
1211:                        assert false : "unknown primitive type"; //NOI18N
1212:                        defValue = maker.Literal(new Integer(0));
1213:                        break;
1214:                    }
1215:                } else if ((typeKind == TypeKind.DECLARED)
1216:                        && type.toString().equals("java.lang.String")) { //NOI18N
1217:                    defValue = maker.Literal(""); //NOI18N
1218:                } else {
1219:                    defValue = maker.Literal(null);
1220:                }
1221:                return defValue;
1222:            }
1223:
1224:            /**
1225:             */
1226:            private ExpressionTree generateNoArgConstructorCall(
1227:                    TreeMaker maker, TypeElement cls) {
1228:                return maker.NewClass(null, //enclosing instance
1229:                        Collections.<ExpressionTree> emptyList(),//type arguments
1230:                        maker.QualIdent(cls), //class identifier
1231:                        Collections.<ExpressionTree> emptyList(),//arguments list
1232:                        null); //class body
1233:            }
1234:
1235:            /**
1236:             */
1237:            private List<ExecutableElement> findTestableMethods(
1238:                    TypeElement classElem) {
1239:                List<ExecutableElement> methods = ElementFilter
1240:                        .methodsIn(classElem.getEnclosedElements());
1241:
1242:                if (methods.isEmpty()) {
1243:                    return Collections.<ExecutableElement> emptyList();
1244:                }
1245:
1246:                List<ExecutableElement> testableMethods = null;
1247:
1248:                int skippedCount = 0;
1249:                for (ExecutableElement method : methods) {
1250:                    if (isTestableMethod(method)) {
1251:                        if (testableMethods == null) {
1252:                            testableMethods = new ArrayList<ExecutableElement>(
1253:                                    methods.size() - skippedCount);
1254:                        }
1255:                        testableMethods.add(method);
1256:                    } else {
1257:                        skippedCount++;
1258:                    }
1259:                }
1260:
1261:                return (testableMethods != null) ? testableMethods
1262:                        : Collections.<ExecutableElement> emptyList();
1263:            }
1264:
1265:            /**
1266:             */
1267:            private boolean isTestableMethod(ExecutableElement method) {
1268:                if (method.getKind() != ElementKind.METHOD) {
1269:                    throw new IllegalArgumentException();
1270:                }
1271:
1272:                return setup.isMethodTestable(method);
1273:            }
1274:
1275:            /**
1276:             */
1277:            protected boolean hasAccessibleNoArgConstructor(TypeElement srcClass) {
1278:                boolean answer;
1279:
1280:                List<ExecutableElement> constructors = ElementFilter
1281:                        .constructorsIn(srcClass.getEnclosedElements());
1282:
1283:                if (constructors.isEmpty()) {
1284:                    answer = true; //no explicit constructor -> synthetic no-arg. constructor
1285:                } else {
1286:                    answer = false;
1287:                    for (ExecutableElement constructor : constructors) {
1288:                        if (constructor.getParameters().isEmpty()) {
1289:                            answer = !constructor.getModifiers().contains(
1290:                                    Modifier.PRIVATE);
1291:                            break;
1292:                        }
1293:                    }
1294:                }
1295:                return answer;
1296:            }
1297:
1298:            /**
1299:             */
1300:            private boolean throwsNonRuntimeExceptions(
1301:                    CompilationInfo compInfo, ExecutableElement method) {
1302:                List<? extends TypeMirror> thrownTypes = method
1303:                        .getThrownTypes();
1304:                if (thrownTypes.isEmpty()) {
1305:                    return false;
1306:                }
1307:
1308:                String runtimeExcName = "java.lang.RuntimeException"; //NOI18N
1309:                TypeElement runtimeExcElement = compInfo.getElements()
1310:                        .getTypeElement(runtimeExcName);
1311:                if (runtimeExcElement == null) {
1312:                    Logger.getLogger("junit").log( //NOI18N
1313:                            Level.WARNING, "Could not find TypeElement for " //NOI18N
1314:                                    + runtimeExcName);
1315:                    return true;
1316:                }
1317:
1318:                Types types = compInfo.getTypes();
1319:                TypeMirror runtimeExcType = runtimeExcElement.asType();
1320:                for (TypeMirror exceptionType : thrownTypes) {
1321:                    if (!types.isSubtype(exceptionType, runtimeExcType)) {
1322:                        return true;
1323:                    }
1324:                }
1325:
1326:                return false;
1327:            }
1328:
1329:            /**
1330:             */
1331:            private <T extends Element> List<T> resolveHandles(
1332:                    CompilationInfo compInfo, List<ElementHandle<T>> handles) {
1333:                if (handles == null) {
1334:                    return null;
1335:                }
1336:                if (handles.isEmpty()) {
1337:                    return Collections.<T> emptyList();
1338:                }
1339:
1340:                List<T> elements = new ArrayList<T>(handles.size());
1341:                for (ElementHandle<T> handle : handles) {
1342:                    T element = handle.resolve(compInfo);
1343:                    if (element != null) {
1344:                        elements.add(element);
1345:                    } else {
1346:                        ErrorManager.getDefault().log(ErrorManager.WARNING,
1347:                                "JUnit: Could not resolve element handle " //NOI18N
1348:                                        + handle.getBinaryName());
1349:                    }
1350:                }
1351:                return elements;
1352:            }
1353:
1354:            /**
1355:             * Stops this creator - cancels creation of a test class.
1356:             */
1357:            public void cancel() {
1358:                cancelled = true;
1359:            }
1360:
1361:            /**
1362:             */
1363:            private void classProcessed(ClassTree cls) {
1364:                if (processedClassNames == null) {
1365:                    processedClassNames = new ArrayList<String>(4);
1366:                }
1367:                processedClassNames.add(cls.getSimpleName().toString());
1368:            }
1369:
1370:            /**
1371:             */
1372:            List<String> getProcessedClassNames() {
1373:                return processedClassNames != null ? processedClassNames
1374:                        : Collections.<String> emptyList();
1375:            }
1376:
1377:            /* private methods */
1378:
1379:            //XXX: retouche
1380:            //    /**
1381:            //     *
1382:            //     * @param cls JavaClass to generate the comment to.
1383:            //     */
1384:            //    private static void addClassBodyComment(JavaClass cls) {
1385:            //        int off = cls.getEndOffset() - 1;        
1386:            //        String theComment1 = NbBundle.getMessage(TestCreator.class,
1387:            //                                                 CLASS_COMMENT_LINE1);
1388:            //        String theComment2 = NbBundle.getMessage(TestCreator.class,
1389:            //                                                 CLASS_COMMENT_LINE2);
1390:            //        String indent = getIndentString();
1391:            //        DiffElement diff = new DiffElement(
1392:            //                off,
1393:            //                off,
1394:            //                indent + theComment1 + '\n'
1395:            //                + indent + theComment2 + '\n' + '\n');
1396:            //        ((ResourceImpl) cls.getResource()).addExtDiff(diff);
1397:            //    }
1398:            /**
1399:             */
1400:            private String getInitialMainMethodBody() {
1401:                if (initialMainMethodBody == null) {
1402:                    initialMainMethodBody = JUnitSettings.getDefault()
1403:                            .getGenerateMainMethodBody();
1404:                    if (initialMainMethodBody == null) {
1405:                        /*
1406:                         * set it to a non-null value so that this method does not try
1407:                         * to load it from the settings next time
1408:                         */
1409:                        initialMainMethodBody = ""; //NOI18N
1410:                    }
1411:                }
1412:                return initialMainMethodBody;
1413:            }
1414:
1415:            /**
1416:             */
1417:            protected ModifiersTree createModifiersTree(
1418:                    String annotationClassName, Set<Modifier> modifiers,
1419:                    WorkingCopy workingCopy) {
1420:                TreeMaker maker = workingCopy.getTreeMaker();
1421:                AnnotationTree annotation = maker
1422:                        .Annotation(getClassIdentifierTree(annotationClassName,
1423:                                workingCopy), Collections
1424:                                .<ExpressionTree> emptyList());
1425:                return maker.Modifiers(modifiers, Collections
1426:                        .<AnnotationTree> singletonList(annotation));
1427:            }
1428:
1429:            /** */
1430:            private Map<String, ExpressionTree> classIdentifiers;
1431:
1432:            /**
1433:             */
1434:            protected ExpressionTree getClassIdentifierTree(String className,
1435:                    WorkingCopy workingCopy) {
1436:                ExpressionTree classIdentifier;
1437:                if (classIdentifiers == null) {
1438:                    classIdentifier = null;
1439:                    classIdentifiers = new HashMap<String, ExpressionTree>(13);
1440:                } else {
1441:                    classIdentifier = classIdentifiers.get(className);
1442:                }
1443:                if (classIdentifier == null) {
1444:                    TypeElement typeElement = getElemForClassName(className,
1445:                            workingCopy.getElements());
1446:                    TreeMaker maker = workingCopy.getTreeMaker();
1447:                    classIdentifier = (typeElement != null) ? maker
1448:                            .QualIdent(typeElement) : maker
1449:                            .Identifier(className);
1450:                    classIdentifiers.put(className, classIdentifier);
1451:                }
1452:                return classIdentifier;
1453:            }
1454:
1455:            /**
1456:             */
1457:            protected static TypeElement getElemForClassName(String className,
1458:                    Elements elements) {
1459:                TypeElement elem = elements.getTypeElement(className);
1460:                if (elem == null) {
1461:                    ErrorManager.getDefault().log(ErrorManager.ERROR,
1462:                            "Could not find TypeElement for " + className); //NOI18N
1463:                }
1464:                return elem;
1465:            }
1466:
1467:            /**
1468:             * Creates a {@code Set} of {@code Modifier}s from the given list
1469:             * of modifiers.
1470:             * 
1471:             * @param  modifiers  modifiers that should be contained in the set
1472:             * @return  set containing exactly the given modifiers
1473:             */
1474:            static Set<Modifier> createModifierSet(Modifier... modifiers) {
1475:                EnumSet<Modifier> modifierSet = EnumSet.noneOf(Modifier.class);
1476:                for (Modifier m : modifiers) {
1477:                    modifierSet.add(m);
1478:                }
1479:                return modifierSet;
1480:            }
1481:
1482:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.