Initial check-in with two inspections working.
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
package de.platon42.intellij.jupiter;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
public @interface AddLocalJarToModule {
|
||||
Class[] value();
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
package de.platon42.intellij.jupiter;
|
||||
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
|
||||
import com.intellij.openapi.roots.ContentEntry;
|
||||
import com.intellij.openapi.roots.ModifiableRootModel;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import com.intellij.testFramework.UsefulTestCase;
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture;
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.extension.*;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext.Store;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class LightCodeInsightExtension implements ParameterResolver, AfterTestExecutionCallback {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(LightCodeInsightExtension.class.getName());
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
|
||||
Parameter parameter = parameterContext.getParameter();
|
||||
return parameter.isAnnotationPresent(MyFixture.class)
|
||||
|| parameter.isAnnotationPresent(MyTestCase.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
|
||||
LightCodeInsightFixtureTestCaseWrapper testCase = getWrapper(extensionContext);
|
||||
Parameter parameter = parameterContext.getParameter();
|
||||
if (parameter.isAnnotationPresent(MyFixture.class)) {
|
||||
return testCase.getMyFixture();
|
||||
} else if (parameter.isAnnotationPresent(MyTestCase.class)) {
|
||||
return testCase;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private LightCodeInsightFixtureTestCaseWrapper getWrapper(ExtensionContext extensionContext) {
|
||||
Store store = getStore(extensionContext);
|
||||
return (LightCodeInsightFixtureTestCaseWrapper) store.getOrComputeIfAbsent("testCase",
|
||||
key -> {
|
||||
LightCodeInsightFixtureTestCaseWrapper wrapper = new LightCodeInsightFixtureTestCaseWrapper(extensionContext);
|
||||
try {
|
||||
wrapper.setUp();
|
||||
} catch (Exception e) {
|
||||
LOG.severe("Exception during setUp(): " + e);
|
||||
throw new IllegalStateException("Exception during setUp()", e);
|
||||
}
|
||||
return wrapper;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTestExecution(ExtensionContext context) throws Exception {
|
||||
Store store = getStore(context);
|
||||
LightCodeInsightFixtureTestCaseWrapper testCase = (LightCodeInsightFixtureTestCaseWrapper) store.get("testCase");
|
||||
if (testCase != null) {
|
||||
testCase.tearDown();
|
||||
}
|
||||
}
|
||||
|
||||
private static Store getStore(ExtensionContext context) {
|
||||
return context.getStore(Namespace.create(LightCodeInsightExtension.class, context.getRequiredTestMethod()));
|
||||
}
|
||||
|
||||
private static class LightCodeInsightFixtureTestCaseWrapper extends LightCodeInsightFixtureTestCase {
|
||||
private final ExtensionContext extensionContext;
|
||||
|
||||
private LightCodeInsightFixtureTestCaseWrapper(ExtensionContext extensionContext) {
|
||||
this.extensionContext = extensionContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
UsefulTestCase.clearFields(this);
|
||||
if (myFixture != null && getProject() != null && !getProject().isDisposed()) {
|
||||
Disposer.dispose(getProject());
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected LightProjectDescriptor getProjectDescriptor() {
|
||||
TestJdk testJdk = getMethodOrClassAnnotation(TestJdk.class);
|
||||
if (testJdk == null) {
|
||||
return super.getProjectDescriptor();
|
||||
}
|
||||
return new ProjectDescriptor(testJdk.value(), testJdk.annotations()) {
|
||||
@Override
|
||||
public Sdk getSdk() {
|
||||
return testJdk.useInternal()
|
||||
? JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk()
|
||||
: super.getSdk();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ContentEntry contentEntry) {
|
||||
super.configureModule(module, model, contentEntry);
|
||||
AddLocalJarToModule methodOrClassAnnotation = getMethodOrClassAnnotation(AddLocalJarToModule.class);
|
||||
if (methodOrClassAnnotation != null) {
|
||||
Stream.of(methodOrClassAnnotation.value()).forEach(it -> addJarContaining(model, it));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected void addJarContaining(ModifiableRootModel model, Class clazz) {
|
||||
try {
|
||||
Path jarPath = Paths.get(clazz.getProtectionDomain().getCodeSource().getLocation().toURI());
|
||||
|
||||
VirtualFile jarFile = LocalFileSystem.getInstance().findFileByIoFile(jarPath.toFile());
|
||||
myFixture.allowTreeAccessForFile(jarFile);
|
||||
PsiTestUtil.addLibrary(
|
||||
myFixture.getModule(),
|
||||
model,
|
||||
jarPath.getFileName().toString().replace(".jar", ""),
|
||||
jarPath.getParent().toString(),
|
||||
jarPath.getFileName().toString()
|
||||
);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IllegalArgumentException("Class URL malformed", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
TestDataPath testDataPath = getMethodOrClassAnnotation(TestDataPath.class);
|
||||
if (testDataPath == null) {
|
||||
return super.getTestDataPath();
|
||||
}
|
||||
TestDataSubPath testDataSubPath = getMethodOrClassAnnotation(TestDataSubPath.class);
|
||||
if (testDataSubPath == null) {
|
||||
return testDataPath.value();
|
||||
}
|
||||
return Paths.get(testDataPath.value(), testDataSubPath.value()).toString();
|
||||
}
|
||||
|
||||
public JavaCodeInsightTestFixture getMyFixture() {
|
||||
return myFixture;
|
||||
}
|
||||
|
||||
private <T extends Annotation> T getMethodOrClassAnnotation(Class<T> clazz) {
|
||||
T annotation = extensionContext.getRequiredTestMethod().getAnnotation(clazz);
|
||||
if (annotation == null) {
|
||||
annotation = extensionContext.getRequiredTestClass().getAnnotation(clazz);
|
||||
}
|
||||
return annotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package de.platon42.intellij.jupiter;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MyFixture {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package de.platon42.intellij.jupiter;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MyTestCase {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package de.platon42.intellij.jupiter;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
public @interface TestDataPath {
|
||||
String value();
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package de.platon42.intellij.jupiter;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
public @interface TestDataSubPath {
|
||||
String value();
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package de.platon42.intellij.jupiter;
|
||||
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
public @interface TestJdk {
|
||||
LanguageLevel value();
|
||||
|
||||
boolean annotations() default false;
|
||||
|
||||
boolean useInternal() default false;
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package de.platon42.intellij.jupiter;
|
||||
|
||||
import com.intellij.testFramework.EdtTestUtilKt;
|
||||
import com.intellij.testFramework.TestLoggerFactory;
|
||||
import com.intellij.testFramework.fixtures.IdeaTestExecutionPolicy;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
// See https://github.com/junit-team/junit5/issues/157
|
||||
public class WorkaroundUntilJupiterGetsExecutorProvider {
|
||||
|
||||
protected static void runTest(Runnable test) throws Throwable {
|
||||
Throwable[] throwables = new Throwable[1];
|
||||
|
||||
Runnable runnable = () -> {
|
||||
try {
|
||||
TestLoggerFactory.onTestStarted();
|
||||
test.run();
|
||||
TestLoggerFactory.onTestFinished(true);
|
||||
} catch (Throwable e) {
|
||||
TestLoggerFactory.onTestFinished(false);
|
||||
e.fillInStackTrace();
|
||||
throwables[0] = e;
|
||||
}
|
||||
};
|
||||
|
||||
invokeTestRunnable(runnable);
|
||||
|
||||
if (throwables[0] != null) {
|
||||
throw throwables[0];
|
||||
}
|
||||
}
|
||||
|
||||
private static void invokeTestRunnable(@NotNull Runnable runnable) {
|
||||
IdeaTestExecutionPolicy policy = IdeaTestExecutionPolicy.current();
|
||||
if (policy != null && !policy.runInDispatchThread()) {
|
||||
runnable.run();
|
||||
} else {
|
||||
EdtTestUtilKt.runInEdtAndWait(() -> {
|
||||
runnable.run();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package de.platon42.intellij.playground;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class Playground {
|
||||
|
||||
private void sizeOfList() {
|
||||
assertThat(new ArrayList<>().size()).isEqualTo(1);
|
||||
}
|
||||
|
||||
private void sizeOfArray() {
|
||||
assertThat(new String[1].length).isLessThanOrEqualTo(1);
|
||||
assertThat(new String[1]).hasSameSizeAs(new Object());
|
||||
assertThat("").isEqualTo(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package de.platon42.intellij.plugins.cajon
|
||||
|
||||
import com.intellij.pom.java.LanguageLevel
|
||||
import com.intellij.testFramework.TestLoggerFactory
|
||||
import com.intellij.testFramework.fixtures.IdeaTestExecutionPolicy
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
||||
import com.intellij.testFramework.runInEdtAndWait
|
||||
import de.platon42.intellij.jupiter.AddLocalJarToModule
|
||||
import de.platon42.intellij.jupiter.LightCodeInsightExtension
|
||||
import de.platon42.intellij.jupiter.TestDataPath
|
||||
import de.platon42.intellij.jupiter.TestJdk
|
||||
import org.assertj.core.api.Assertions
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
|
||||
@ExtendWith(LightCodeInsightExtension::class)
|
||||
@TestDataPath("src/test/resources")
|
||||
@TestJdk(LanguageLevel.JDK_1_8, annotations = true, useInternal = true)
|
||||
@AddLocalJarToModule(Assertions::class)
|
||||
abstract class AbstractCajonTest {
|
||||
|
||||
// See https://github.com/junit-team/junit5/issues/157
|
||||
protected fun runTest(body: () -> Unit) {
|
||||
val throwables = arrayOfNulls<Throwable>(1)
|
||||
|
||||
invokeTestRunnable {
|
||||
try {
|
||||
TestLoggerFactory.onTestStarted()
|
||||
body()
|
||||
TestLoggerFactory.onTestFinished(true)
|
||||
} catch (e: InvocationTargetException) {
|
||||
TestLoggerFactory.onTestFinished(false)
|
||||
e.fillInStackTrace()
|
||||
throwables[0] = e.targetException
|
||||
} catch (e: IllegalAccessException) {
|
||||
TestLoggerFactory.onTestFinished(false)
|
||||
e.fillInStackTrace()
|
||||
throwables[0] = e
|
||||
} catch (e: Throwable) {
|
||||
TestLoggerFactory.onTestFinished(false)
|
||||
throwables[0] = e
|
||||
}
|
||||
}
|
||||
|
||||
if (throwables[0] != null) {
|
||||
throw throwables[0]!!
|
||||
}
|
||||
}
|
||||
|
||||
private fun invokeTestRunnable(runnable: () -> Unit) {
|
||||
val policy = IdeaTestExecutionPolicy.current()
|
||||
if (policy != null && !policy.runInDispatchThread()) {
|
||||
runnable()
|
||||
} else {
|
||||
runInEdtAndWait {
|
||||
runnable()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun executeQuickFixes(myFixture: JavaCodeInsightTestFixture, expectedFixes: Int) {
|
||||
val quickfixes = myFixture.getAllQuickFixes()
|
||||
assertThat(quickfixes).hasSize(expectedFixes)
|
||||
quickfixes.forEach(myFixture::launchAction)
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package de.platon42.intellij.plugins.cajon.inspections
|
||||
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
||||
import de.platon42.intellij.jupiter.MyFixture
|
||||
import de.platon42.intellij.jupiter.TestDataSubPath
|
||||
import de.platon42.intellij.plugins.cajon.AbstractCajonTest
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
internal class AssertThatObjectIsNotNullInspectionTest : AbstractCajonTest() {
|
||||
|
||||
@Test
|
||||
@TestDataSubPath("inspections/ObjectIsNotNull")
|
||||
internal fun assertThat_with_isNotEqualTo_null_can_use_isNotNull(@MyFixture myFixture: JavaCodeInsightTestFixture) {
|
||||
runTest {
|
||||
myFixture.enableInspections(AssertThatObjectIsNotNullInspection::class.java)
|
||||
myFixture.configureByFile("ObjectIsNotNullBefore.java")
|
||||
executeQuickFixes(myFixture, 3)
|
||||
myFixture.checkResultByFile("ObjectIsNotNullAfter.java")
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package de.platon42.intellij.plugins.cajon.inspections
|
||||
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
||||
import de.platon42.intellij.jupiter.MyFixture
|
||||
import de.platon42.intellij.jupiter.TestDataSubPath
|
||||
import de.platon42.intellij.plugins.cajon.AbstractCajonTest
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
internal class AssertThatObjectIsNullInspectionTest : AbstractCajonTest() {
|
||||
|
||||
@Test
|
||||
@TestDataSubPath("inspections/ObjectIsNull")
|
||||
internal fun assertThat_with_isEqualTo_null_can_use_isNull(@MyFixture myFixture: JavaCodeInsightTestFixture) {
|
||||
runTest {
|
||||
myFixture.enableInspections(AssertThatObjectIsNullInspection::class.java)
|
||||
myFixture.configureByFile("ObjectIsNullBefore.java")
|
||||
executeQuickFixes(myFixture, 3)
|
||||
myFixture.checkResultByFile("ObjectIsNullAfter.java")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user