Skip to content

Commit 6acbaa2

Browse files
authored
Merge pull request #95 from hza/various-test-engines-support
test engines support: AssertJ, JUnit 4/5, TestNG, JDK assert with auto-detection.
2 parents ae91ded + f7c9bbc commit 6acbaa2

File tree

35 files changed

+505
-83
lines changed

35 files changed

+505
-83
lines changed

src/main/java/com/bruce/intellijplugin/generatesetter/CommonConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public class CommonConstants {
2424
public static final String GENERATE_ACCESSORS_METHOD = "Generate accessors chain call";
2525
public static final String GENERATE_SETTER_METHOD_NO_DEFAULT_VALUE = "Generate all setter no default value";
2626
public static final String ASSERT_ALL_PROPS = "Assert all getters";
27+
public static final String ASSERT_NOT_NULL = "Assert is not null";
2728
public static final String GENERATE_CONVERTER_FROM_METHOD = "Generate setter getter converter";
2829
public static final String BUILDER_CONVERTER_FROM_METHOD = "Generate builder getter converter";
2930
public static final String BUILDER_METHOD_NAME = "builder";

src/main/java/com/bruce/intellijplugin/generatesetter/GenerateAllHandlerAdapter.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
import com.bruce.intellijplugin.generatesetter.actions.GenerateAllHandler;
1818

19+
import java.util.Set;
20+
1921
/**
2022
* @author bruce ge
2123
*/
@@ -49,4 +51,14 @@ public boolean forBuilder() {
4951
public boolean forAccessor() {
5052
return false;
5153
}
54+
55+
@Override
56+
public boolean forAssertWithDefaultValues() {
57+
return false;
58+
}
59+
60+
@Override
61+
public void appendImportList(Set<String> newImportList) {
62+
// nothing
63+
}
5264
}
Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
/*
2+
* Copyright (c) 2017-2023, bruce.ge.
3+
* This program is free software; you can redistribute it and/or
4+
* modify it under the terms of the GNU General Public License
5+
* as published by the Free Software Foundation; version 2 of
6+
* the License.
7+
* This program is distributed in the hope that it will be useful,
8+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
9+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10+
* GNU General Public License for more details.
11+
* You should have received a copy of the GNU General Public License
12+
* along with this program;
13+
*/
14+
15+
package com.bruce.intellijplugin.generatesetter.actions;
16+
17+
import com.bruce.intellijplugin.generatesetter.CommonConstants;
18+
import com.bruce.intellijplugin.generatesetter.GenerateAllHandlerAdapter;
19+
import com.google.common.collect.ImmutableMap;
20+
import com.intellij.openapi.editor.Editor;
21+
import com.intellij.openapi.module.Module;
22+
import com.intellij.openapi.project.Project;
23+
import com.intellij.openapi.roots.ProjectFileIndex;
24+
import com.intellij.openapi.roots.ProjectRootManager;
25+
import com.intellij.openapi.vfs.VirtualFile;
26+
import com.intellij.psi.PsiClass;
27+
import com.intellij.psi.PsiElement;
28+
import com.intellij.psi.PsiFile;
29+
import com.intellij.psi.PsiImportList;
30+
import com.intellij.psi.PsiImportStatement;
31+
import com.intellij.psi.PsiImportStaticStatement;
32+
import com.intellij.psi.PsiJavaFile;
33+
import com.intellij.psi.search.GlobalSearchScope;
34+
import com.intellij.psi.search.PsiShortNamesCache;
35+
import org.jetbrains.annotations.NotNull;
36+
37+
import java.util.HashSet;
38+
import java.util.Map;
39+
import java.util.Set;
40+
41+
import static com.bruce.intellijplugin.generatesetter.actions.AssertAllGetterAction.TestEngine.ASSERT;
42+
import static com.bruce.intellijplugin.generatesetter.actions.AssertAllGetterAction.TestEngine.ASSERTJ;
43+
import static com.bruce.intellijplugin.generatesetter.actions.AssertAllGetterAction.TestEngine.JUNIT4;
44+
import static com.bruce.intellijplugin.generatesetter.actions.AssertAllGetterAction.TestEngine.JUNIT5;
45+
import static com.bruce.intellijplugin.generatesetter.actions.AssertAllGetterAction.TestEngine.TESTNG;
46+
47+
/**
48+
* @author bruce ge
49+
*/
50+
public class AssertAllGetterAction extends GenerateAllSetterBase {
51+
enum TestEngine {ASSERT, JUNIT4, JUNIT5, TESTNG, ASSERTJ}
52+
53+
// imports to add when generating asserts.
54+
private static final Map<TestEngine, String> engineImports = ImmutableMap.<TestEngine, String>builder()
55+
.put(JUNIT4, "static org.junit.Assert.assertEquals")
56+
.put(JUNIT5, "static org.junit.jupiter.api.Assertions.assertEquals")
57+
.put(TESTNG, "static org.testng.Assert.assertEquals")
58+
.put(ASSERTJ, "static org.assertj.core.api.Assertions.assertThat")
59+
.put(ASSERT, "java.util.Objects")
60+
.build();
61+
62+
// className like 'java.util.Objects' -> engine (only java.util.Objects)
63+
private static final Map<String, TestEngine> enginePlainImportsReversed = ImmutableMap.<String, TestEngine>builder()
64+
.put("java.util.Objects", ASSERT)
65+
.build();
66+
67+
// static className -> engine
68+
private static final Map<String, TestEngine> engineStaticImportsReversed = ImmutableMap.<String, TestEngine>builder()
69+
.put("org.junit.Assert", JUNIT4)
70+
.put("org.junit.jupiter.api.Assertions", JUNIT5)
71+
.put("org.testng.Assert", TESTNG)
72+
.put("org.assertj.core.api.Assertions", ASSERTJ)
73+
.build();
74+
75+
// engine -> assert static method
76+
private static final Map<TestEngine, String> engineStaticImportsMethod = ImmutableMap.<TestEngine, String>builder()
77+
.put(JUNIT4, "assertEquals")
78+
.put(JUNIT5, "assertEquals")
79+
.put(TESTNG, "assertEquals")
80+
.put(ASSERTJ, "assertThat")
81+
.build();
82+
83+
protected Project project;
84+
protected PsiFile containingFile;
85+
86+
public AssertAllGetterAction() {
87+
setGenerateAllHandler(new GenerateAllAssertsHandlerAdapter(true));
88+
}
89+
90+
@NotNull
91+
@Override
92+
public String getText() {
93+
return CommonConstants.ASSERT_ALL_PROPS;
94+
}
95+
96+
@Override
97+
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
98+
PsiFile containingFile = element.getContainingFile();
99+
if (containingFile == null) {
100+
return false;
101+
}
102+
VirtualFile virtualFile = containingFile.getVirtualFile();
103+
if (virtualFile == null) {
104+
return false;
105+
}
106+
107+
ProjectRootManager instance = ProjectRootManager.getInstance(element.getProject());
108+
boolean inTestSourceContent = instance.getFileIndex().isInTestSourceContent(virtualFile);
109+
110+
if (inTestSourceContent) {
111+
this.project = project;
112+
this.containingFile = containingFile;
113+
return super.isAvailable(project, editor, element);
114+
}
115+
return false;
116+
}
117+
118+
119+
class GenerateAllAssertsHandlerAdapter extends GenerateAllHandlerAdapter {
120+
private final boolean generateWithDefaultValues;
121+
122+
protected final Set<TestEngine> currentFileImportedEngines = new HashSet<>();
123+
protected TestEngine currentFileTestEngine = TestEngine.ASSERT;
124+
125+
public GenerateAllAssertsHandlerAdapter(boolean generateWithDefaultValues) {
126+
this.generateWithDefaultValues = generateWithDefaultValues;
127+
}
128+
129+
public void detectCurrentTestEngine(Project project, PsiFile containingFile) {
130+
currentFileTestEngine = detectCurrentTestEngineInternal(project, containingFile);
131+
}
132+
133+
private TestEngine detectCurrentTestEngineInternal(Project project, PsiFile containingFile) {
134+
135+
if (containingFile instanceof PsiJavaFile) {
136+
PsiJavaFile javaFile = (PsiJavaFile) containingFile;
137+
PsiImportList importList = javaFile.getImportList();
138+
139+
// prefer AssertJ if it is in classpath
140+
ProjectFileIndex index = ProjectFileIndex.getInstance(project);
141+
Module module = index.getModuleForFile(containingFile.getVirtualFile());
142+
if (module != null) {
143+
GlobalSearchScope searchScope = GlobalSearchScope.moduleRuntimeScope(module, true);
144+
PsiClass[] lists = PsiShortNamesCache.getInstance(project)
145+
.getClassesByName("Assertions", searchScope);
146+
147+
for (PsiClass psiClass : lists) {
148+
if ("org.assertj.core.api.Assertions".equals(psiClass.getName())) {
149+
detectImportedEngines(importList);
150+
return ASSERTJ;
151+
}
152+
}
153+
}
154+
155+
156+
if (importList != null) {
157+
detectImportedEngines(importList);
158+
159+
PsiImportStatement[] importStatements = importList.getImportStatements();
160+
161+
for (PsiImportStatement importStatement : importStatements) {
162+
String qualifiedName = importStatement.getQualifiedName();
163+
if (qualifiedName == null) {
164+
continue;
165+
}
166+
167+
if (qualifiedName.startsWith("org.junit.jupiter.api.")) {
168+
return TestEngine.JUNIT5;
169+
}
170+
if (qualifiedName.startsWith("org.junit.")) {
171+
return TestEngine.JUNIT4;
172+
}
173+
if (qualifiedName.startsWith("org.assertj.")) {
174+
return TestEngine.ASSERTJ;
175+
}
176+
if (qualifiedName.startsWith("org.testng.")) {
177+
return TestEngine.TESTNG;
178+
}
179+
}
180+
}
181+
}
182+
183+
return TestEngine.ASSERT;
184+
}
185+
186+
private void detectImportedEngines(PsiImportList importList) {
187+
currentFileImportedEngines.clear();
188+
189+
if (importList == null) {
190+
return;
191+
}
192+
193+
PsiImportStaticStatement[] importStaticStatements = importList.getImportStaticStatements();
194+
195+
for (PsiImportStaticStatement importStaticStatement : importStaticStatements) {
196+
PsiClass psiClass = importStaticStatement.resolveTargetClass();
197+
if (psiClass == null) {
198+
continue;
199+
}
200+
201+
String qualifiedName = psiClass.getQualifiedName();
202+
TestEngine testEngine = engineStaticImportsReversed.get(qualifiedName);
203+
if (testEngine != null) {
204+
String referenceName = importStaticStatement.getReferenceName(); // like assertEquals
205+
if (referenceName == null || referenceName.equals(engineStaticImportsMethod.get(testEngine))) {
206+
currentFileImportedEngines.add(testEngine);
207+
}
208+
}
209+
}
210+
211+
PsiImportStatement[] importStatements = importList.getImportStatements();
212+
213+
for (PsiImportStatement importStatement : importStatements) {
214+
String qualifiedName = importStatement.getQualifiedName();
215+
if (qualifiedName == null) {
216+
continue;
217+
}
218+
219+
TestEngine testEngine = enginePlainImportsReversed.get(qualifiedName);
220+
if (testEngine != null) {
221+
currentFileImportedEngines.add(testEngine);
222+
}
223+
}
224+
}
225+
226+
@Override
227+
public boolean isSetter() {
228+
return false;
229+
}
230+
231+
@Override
232+
public boolean shouldAddDefaultValue() {
233+
return generateWithDefaultValues;
234+
}
235+
236+
@Override
237+
public boolean forAssertWithDefaultValues() {
238+
return generateWithDefaultValues;
239+
}
240+
241+
@Override
242+
public String formatLine(String line) {
243+
String getter, value;
244+
245+
if (forAssertWithDefaultValues()) {
246+
int index = line.indexOf("(");
247+
getter = line.substring(0, index + 1) + ")";
248+
value = line.substring(index + 1, line.length() - 2);
249+
} else {
250+
getter = line.substring(0, line.length() - 1);
251+
value = "";
252+
}
253+
254+
detectCurrentTestEngine(project, containingFile);
255+
256+
switch (currentFileTestEngine) {
257+
case JUNIT4:
258+
case JUNIT5:
259+
return "assertEquals(" + value + ", " + getter + ");";
260+
case TESTNG:
261+
return "assertEquals(" + getter + ", " + value + ");";
262+
case ASSERTJ:
263+
return "assertThat(" + getter + ").isEqualTo(" + value + ");";
264+
case ASSERT:
265+
return "assert Objects.equals(" + value + ", " + getter + ");";
266+
default:
267+
throw new Error("Unknown case: " + currentFileTestEngine);
268+
}
269+
}
270+
271+
@Override
272+
public void appendImportList(Set<String> newImportList) {
273+
if (!currentFileImportedEngines.contains(currentFileTestEngine)) {
274+
newImportList.add(engineImports.get(currentFileTestEngine));
275+
}
276+
}
277+
}
278+
}

src/main/java/com/bruce/intellijplugin/generatesetter/actions/AssertJAssertAllGetterAction.java

Lines changed: 0 additions & 68 deletions
This file was deleted.

0 commit comments

Comments
 (0)