|
61 | 61 | import org.eclipse.jdt.ls.core.internal.ChangeUtil;
|
62 | 62 | import org.eclipse.jdt.ls.core.internal.JDTUtils;
|
63 | 63 | import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
|
| 64 | +import org.eclipse.jdt.ls.core.internal.ProjectUtils; |
64 | 65 | import org.eclipse.jdt.ls.core.internal.handlers.CodeGenerationUtils;
|
65 | 66 | import org.eclipse.jdt.ls.core.internal.text.correction.SourceAssistProcessor;
|
66 | 67 | import org.eclipse.lsp4j.MessageType;
|
@@ -180,14 +181,17 @@ public static WorkspaceEdit generateTests(List<Object> arguments, IProgressMonit
|
180 | 181 | */
|
181 | 182 | private static WorkspaceEdit generateTestsFromSource(ICompilationUnit unit, ITypeBinding typeBinding,
|
182 | 183 | int cursorOffset) throws CoreException {
|
183 |
| - final IJavaProject javaProject = unit.getJavaProject(); |
| 184 | + final IJavaProject javaProject = determineTestProject(unit); |
| 185 | + if (javaProject == null) { |
| 186 | + return null; |
| 187 | + } |
184 | 188 | final List<TestKind> testFrameworksInProject = TestKindProvider.getTestKindsFromCache(javaProject);
|
185 | 189 | final TestKind testKind = determineTestFramework(new HashSet<>(testFrameworksInProject));
|
186 | 190 | if (testKind == null) {
|
187 | 191 | return null;
|
188 | 192 | }
|
189 | 193 |
|
190 |
| - final IClasspathEntry testEntry = getTestClasspathEntry(unit); |
| 194 | + final IClasspathEntry testEntry = getTestClasspathEntry(javaProject, unit); |
191 | 195 | if (testEntry == null) {
|
192 | 196 | JavaLanguageServerPlugin.getInstance().getClientConnection().showNotificationMessage(MessageType.Error,
|
193 | 197 | "Cannot find a valid classpath entry to generate tests.");
|
@@ -282,7 +286,8 @@ private static WorkspaceEdit addTestMethodsToExistingTestClass(CompilationUnit t
|
282 | 286 | return new MethodMetaData(methodName, testAnnotation);
|
283 | 287 | }).collect(Collectors.toList());
|
284 | 288 |
|
285 |
| - final TextEdit edit = getTextEdit(kind, metadata, testRoot, typeNode, typeBinding, insertPosition); |
| 289 | + final TextEdit edit = getTextEdit(kind, metadata, testRoot, typeNode, typeBinding, insertPosition, |
| 290 | + false /*fromTest*/); |
286 | 291 | return SourceAssistProcessor.convertToWorkspaceEdit((ICompilationUnit) testRoot.getJavaElement(), edit);
|
287 | 292 | }
|
288 | 293 |
|
@@ -352,8 +357,8 @@ private static String constructMethodStub(ICompilationUnit testUnit, TestKind te
|
352 | 357 | lineDelimiter, testUnit.getJavaProject().getOptions(true));
|
353 | 358 | }
|
354 | 359 |
|
355 |
| - private static IClasspathEntry getTestClasspathEntry(ICompilationUnit unit) throws JavaModelException { |
356 |
| - final IJavaProject javaProject = unit.getJavaProject(); |
| 360 | + private static IClasspathEntry getTestClasspathEntry(IJavaProject javaProject, ICompilationUnit unit) |
| 361 | + throws JavaModelException { |
357 | 362 | // In most cases, this is the classpath entry used for testing, we first find the target entry by hard-code
|
358 | 363 | // to avoid go into the generated entries.
|
359 | 364 | IClasspathEntry testEntry = javaProject.getClasspathEntryFor(
|
@@ -563,6 +568,37 @@ private static List<String> determineMethodsToGenerate(List<String> lifecycleAnn
|
563 | 568 | methodList, true /*pickMany*/);
|
564 | 569 | }
|
565 | 570 |
|
| 571 | + private static IJavaProject determineTestProject(ICompilationUnit unit) { |
| 572 | + final IJavaProject javaProject = unit.getJavaProject(); |
| 573 | + if (TestKindProvider.getTestKindsFromCache(javaProject).size() > 0) { |
| 574 | + return javaProject; |
| 575 | + } |
| 576 | + |
| 577 | + final IJavaProject[] javaProjects = ProjectUtils.getJavaProjects(); |
| 578 | + final List<Option> javaTestProjects = new LinkedList<>(); |
| 579 | + for (final IJavaProject project : javaProjects) { |
| 580 | + if (project.equals(JavaLanguageServerPlugin.getProjectsManager().getDefaultProject())) { |
| 581 | + continue; |
| 582 | + } |
| 583 | + if (TestKindProvider.getTestKindsFromCache(project).size() > 0) { |
| 584 | + javaTestProjects.add(new Option(project.getHandleIdentifier(), project.getElementName(), |
| 585 | + project.getProject().getLocation().toOSString())); |
| 586 | + } |
| 587 | + } |
| 588 | + |
| 589 | + if (javaTestProjects.size() == 0) { |
| 590 | + JavaLanguageServerPlugin.getInstance().getClientConnection().showNotificationMessage(MessageType.Error, |
| 591 | + "No test library found in your workspace, please add a test library to your project classpath first."); |
| 592 | + return null; |
| 593 | + } |
| 594 | + final Object result = JUnitPlugin.askClientForChoice("Select a project where tests are generated in", |
| 595 | + javaTestProjects); |
| 596 | + if (result == null) { |
| 597 | + return null; |
| 598 | + } |
| 599 | + return (IJavaProject) JavaCore.create((String) result); |
| 600 | + } |
| 601 | + |
566 | 602 | private static TestKind determineTestFramework(Set<TestKind> availableFrameworks) throws CoreException {
|
567 | 603 | if (availableFrameworks.size() == 0) {
|
568 | 604 | JavaLanguageServerPlugin.getInstance().getClientConnection().showNotificationMessage(MessageType.Error,
|
@@ -619,11 +655,11 @@ private static TextEdit createTextEditFromTestFile(TestKind kind, List<String> m
|
619 | 655 | return new MethodMetaData(methodName, prefix + annotationName);
|
620 | 656 | }).collect(Collectors.toList());
|
621 | 657 |
|
622 |
| - return getTextEdit(kind, metadata, root, typeNode, typeBinding, insertPosition); |
| 658 | + return getTextEdit(kind, metadata, root, typeNode, typeBinding, insertPosition, true /*fromTest*/); |
623 | 659 | }
|
624 | 660 |
|
625 | 661 | private static TextEdit getTextEdit(TestKind kind, List<MethodMetaData> methodMetadata, CompilationUnit root,
|
626 |
| - TypeDeclaration typeNode, ITypeBinding typeBinding, IJavaElement insertPosition) |
| 662 | + TypeDeclaration typeNode, ITypeBinding typeBinding, IJavaElement insertPosition, boolean fromTest) |
627 | 663 | throws CoreException {
|
628 | 664 | final ASTRewrite astRewrite = ASTRewrite.create(root.getAST());
|
629 | 665 | final ImportRewrite importRewrite = StubUtility.createImportRewrite(root, true);
|
@@ -667,7 +703,10 @@ private static TextEdit getTextEdit(TestKind kind, List<MethodMetaData> methodMe
|
667 | 703 | }
|
668 | 704 |
|
669 | 705 | final ASTNode insertion = StubUtility2Core.getNodeToInsertBefore(listRewrite, insertPosition);
|
670 |
| - if (insertion != null) { |
| 706 | + // Only try to insert according to the cursor position when it's triggered from test file, |
| 707 | + // If it's triggered from source file, since code snippets will be generated into a new file, |
| 708 | + // they will always insert to the last. |
| 709 | + if (insertion != null && fromTest) { |
671 | 710 | listRewrite.insertBefore(decl, insertion, null);
|
672 | 711 | } else {
|
673 | 712 | listRewrite.insertLast(decl, null);
|
|
0 commit comments