package de.plushnikov.intellij.plugin;

import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.openapi.projectRoots.JavaSdk;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.psi.PsiClassType;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiMethodCallExpression;
import com.intellij.testFramework.LightCodeInsightTestCase;
import org.jetbrains.annotations.NonNls;

import java.util.List;

/**
 * Based on logic from com.intellij.codeInsight.ExceptionCheckingTest
 */
public class SneakyThrowsTest extends LightCodeInsightTestCase {

  public void testCatchAllException() throws Exception {
    PsiMethodCallExpression methodCall = createCall("@lombok.SneakyThrows void foo() {  throwsMyException(); }");
    List<PsiClassType> exceptions = ExceptionUtil.getUnhandledExceptions(methodCall, null);
    assertTrue(exceptions.isEmpty());
  }

  public void testCatchSpecificException() throws Exception {
    PsiMethodCallExpression methodCall = createCall("@lombok.SneakyThrows(MyException.class) void foo() {  throwsMyException(); }");
    List<PsiClassType> exceptions = ExceptionUtil.getUnhandledExceptions(methodCall, null);
    assertTrue(exceptions.isEmpty());
  }

  public void testCatchGeneralException() throws Exception {
    PsiMethodCallExpression methodCall = createCall("@lombok.SneakyThrows(Exception.class) void foo() {  throwsMyException(); }");
    List<PsiClassType> exceptions = ExceptionUtil.getUnhandledExceptions(methodCall, null);
    assertTrue(exceptions.isEmpty());
  }

  public void testNotCatchException() throws Exception {
    PsiMethodCallExpression methodCall = createCall("@lombok.SneakyThrows(SomeException.class) void foo() {  throwsMyException(); }");
    List<PsiClassType> exceptions = ExceptionUtil.getUnhandledExceptions(methodCall, null);
    assertEquals(1, exceptions.size());
    assertEquals("Test.MyException", exceptions.get(0).getCanonicalText());
  }

  @Override
  protected Sdk getProjectJDK() {
    return JavaSdk.getInstance().createJdk("java 1.8", "lib/mockJDK-1.8", false);
  }

  private static PsiMethodCallExpression createCall(@NonNls final String body) {
    final PsiFile file = createFile("test.java", "class Test { " + body +
      "void throwsMyException() throws MyException {}" +
      "void throwsSomeException() throws SomeException {}" +
      "static class MyException extends Exception {}" +
      "static class SomeException extends Exception {}" +
      "static class Exception {}" +
      "}");
    PsiMethodCallExpression methodCall = findMethodCall(file);
    assertNotNull(methodCall);
    return methodCall;
  }

  private static PsiMethodCallExpression findMethodCall(PsiElement element) {
    if (element instanceof PsiMethodCallExpression) {
      return (PsiMethodCallExpression) element;
    }

    for (PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()) {
      final PsiMethodCallExpression call = findMethodCall(child);
      if (call != null) {
        return call;
      }
    }

    return null;
  }
}

@@ -367,24 +367,28 @@
 mework.Light
+Java
 CodeInsightT
@@ -583,16 +583,20 @@
 ds Light
+Java
 CodeInsi
@@ -647,33 +647,16 @@
 eption()
- throws Exception
  %7B%0A    P
@@ -941,33 +941,16 @@
 eption()
- throws Exception
  %7B%0A    P
@@ -1253,33 +1253,16 @@
 eption()
- throws Exception
  %7B%0A    P
@@ -1563,25 +1563,8 @@
 on()
- throws Exception
  %7B%0A 
@@ -2045,39 +2045,32 @@
 %0A  %7D%0A%0A  private 
-static 
 PsiMethodCallExp

fix test for snapshot build (removed static method)