Package de.plushnikov.lombok

Source Code of de.plushnikov.lombok.LombokParsingTestCase

package de.plushnikov.lombok;

import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.intellij.pom.PomNamedTarget;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiClassType;
import com.intellij.psi.PsiCodeBlock;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiModifierList;
import com.intellij.psi.PsiParameter;
import com.intellij.psi.PsiParameterList;
import com.intellij.psi.PsiReferenceList;
import com.intellij.psi.PsiType;
import org.apache.log4j.Logger;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;

/**
* Base test case for testing that the Lombok plugin parses the Lombok annotations correctly.
*/
public abstract class LombokParsingTestCase extends LombokLightCodeInsightTestCase {

  private static final Logger LOG = Logger.getLogger(LombokParsingTestCase.class);
  private static final Collection<String> MODIFIERS_TO_COMPARE = Collections2.filter(Arrays.asList(PsiModifier.MODIFIERS), Predicates.not(Predicates.equalTo(PsiModifier.DEFAULT)));

  protected boolean shouldCompareInitializers() {
    return true;
  }

  protected boolean shouldCompareAnnotations() {
    return false;
  }

  protected boolean shouldCompareModifiers() {
    return true;
  }

  protected boolean shouldCompareCodeBlocks() {
    return true;
  }

  public void doTest() throws IOException {
    doTest(getTestName(false).replace('$', '/') + ".java");
  }

  protected void doTest(String fileName) throws IOException {
    final PsiFile psiDelombokFile = loadToPsiFile("after/" + fileName);
    final PsiFile psiLombokFile = loadToPsiFile("before/" + fileName);

    if (!(psiLombokFile instanceof PsiJavaFile) || !(psiDelombokFile instanceof PsiJavaFile)) {
      fail("The test file type is not supported");
    }

    final PsiJavaFile beforeFile = (PsiJavaFile) psiLombokFile;
    final PsiJavaFile afterFile = (PsiJavaFile) psiDelombokFile;

    PsiClass[] beforeClasses = beforeFile.getClasses();
    PsiClass[] afterClasses = afterFile.getClasses();

    compareClasses(beforeClasses, afterClasses);
  }

  private void compareClasses(PsiClass[] beforeClasses, PsiClass[] afterClasses) {
    LOG.info("Before innerclasses: " + Arrays.toString(beforeClasses));
    LOG.info("After innerclasses: " + Arrays.toString(afterClasses));

    assertEquals("Class counts are different", afterClasses.length, beforeClasses.length);

    for (PsiClass afterClass : afterClasses) {
      boolean compared = false;
      for (PsiClass beforeClass : beforeClasses) {
        if (afterClass.getName().equals(beforeClass.getName())) {
          compareTwoClasses(beforeClass, afterClass);
          compared = true;
        }
      }
      assertTrue("Class names are not equal, class (" + afterClass.getName() + ") not found", compared);
    }
  }

  private void compareTwoClasses(PsiClass beforeClass, PsiClass afterClass) {
    LOG.info("Comparing classes " + beforeClass.getName() + " with " + afterClass.getName());
    PsiModifierList beforeFieldModifierList = beforeClass.getModifierList();
    PsiModifierList afterFieldModifierList = afterClass.getModifierList();

    compareContainingClasses(beforeClass, afterClass);
    compareModifiers(beforeFieldModifierList, afterFieldModifierList);
    compareFields(beforeClass, afterClass);
    compareMethods(beforeClass, afterClass);
    compareConstructors(beforeClass, afterClass);
    compareInnerClasses(beforeClass, afterClass);

    LOG.debug("Compared classes IntelliJ " + beforeClass.getName() + " with " + afterClass.getName());
  }

  private void compareFields(PsiClass beforeClass, PsiClass afterClass) {
    PsiField[] beforeClassFields = beforeClass.getFields();
    PsiField[] afterClassFields = afterClass.getFields();

    LOG.debug("IntelliJ fields for class " + beforeClass.getName() + ": " + Arrays.toString(beforeClassFields));
    LOG.debug("Theirs fields for class " + afterClass.getName() + ": " + Arrays.toString(afterClassFields));

    assertEquals("Field counts are different for Class " + beforeClass.getName(), afterClassFields.length, beforeClassFields.length);

    for (PsiField afterField : afterClassFields) {
      boolean compared = false;
      final PsiModifierList afterFieldModifierList = afterField.getModifierList();
      for (PsiField beforeField : beforeClassFields) {
        if (afterField.getName().equals(beforeField.getName())) {
          final PsiModifierList beforeFieldModifierList = beforeField.getModifierList();

          compareModifiers(beforeFieldModifierList, afterFieldModifierList);
          compareType(beforeField.getType(), afterField.getType(), afterField);
          compareInitializers(beforeField.getInitializer(), afterField.getInitializer());
          compared = true;
        }
      }
      assertTrue("Fieldnames are not equal, Field (" + afterField.getName() + ") not found", compared);
    }
  }

  private void compareInitializers(PsiExpression beforeInitializer, PsiExpression afterInitializer) {
    if (shouldCompareInitializers()) {
      String beforeInitializerText = null == beforeInitializer ? "" : beforeInitializer.getText();
      String afterInitializerText = null == afterInitializer ? "" : afterInitializer.getText();
      assertEquals(String.format("Initializers are not equals "), afterInitializerText, beforeInitializerText);
    }
  }

  private void compareType(PsiType beforeType, PsiType afterType, PomNamedTarget whereTarget) {
    if (null != beforeType && null != afterType) {
      final String afterText = stripJavaLang(afterType.getCanonicalText());
      final String beforeText = stripJavaLang(beforeType.getCanonicalText());
      assertEquals(String.format("Types are not equal for element: %s", whereTarget.getName()), afterText, beforeText);
    }
  }

  private String stripJavaLang(String canonicalText) {
    final String prefix = "java.lang.";
    if (canonicalText.startsWith(prefix)) {
      canonicalText = canonicalText.substring(prefix.length());
    }
    return canonicalText;
  }

  private void compareModifiers(PsiModifierList beforeModifierList, PsiModifierList afterModifierList) {
    assertNotNull(beforeModifierList);
    assertNotNull(afterModifierList);

    if (shouldCompareModifiers()) {
      for (String modifier : MODIFIERS_TO_COMPARE) {
        assertEquals(modifier + " Modifier is not equal; ", afterModifierList.hasModifierProperty(modifier), beforeModifierList.hasModifierProperty(modifier));
      }
    }
    if (shouldCompareAnnotations()) {
      Collection<String> beforeAnnotations = Lists.newArrayList(Collections2.transform(Arrays.asList(beforeModifierList.getAnnotations()), new QualifiedNameFunction()));
      Collection<String> afterAnnotations = Lists.newArrayList(Collections2.transform(Arrays.asList(afterModifierList.getAnnotations()), new QualifiedNameFunction()));

      Iterables.removeIf(beforeAnnotations, Predicates.containsPattern("lombok.*"));
      assertEquals("Annotationcounts are different ", afterAnnotations.size(), beforeAnnotations.size());
    }
  }


  private void compareMethods(PsiClass beforeClass, PsiClass afterClass) {
    PsiMethod[] beforeMethods = beforeClass.getMethods();
    PsiMethod[] afterMethods = afterClass.getMethods();

    LOG.info("Before methods for class " + beforeClass.getName() + ": " + Arrays.toString(beforeMethods));
    LOG.info("After methods for class " + afterClass.getName() + ": " + Arrays.toString(afterMethods));

    assertEquals("Method counts are different for Class: " + beforeClass.getName(), afterMethods.length, beforeMethods.length);

    for (PsiMethod afterMethod : afterMethods) {
      boolean compared = false;
      final PsiModifierList afterModifierList = afterMethod.getModifierList();
      for (PsiMethod beforeMethod : beforeMethods) {
        if (afterMethod.getName().equals(beforeMethod.getName()) &&
            afterMethod.getParameterList().getParametersCount() == beforeMethod.getParameterList().getParametersCount()) {
          PsiModifierList beforeModifierList = beforeMethod.getModifierList();

          compareModifiers(beforeModifierList, afterModifierList);
          compareType(beforeMethod.getReturnType(), afterMethod.getReturnType(), afterMethod);
          compareParams(beforeMethod.getParameterList(), afterMethod.getParameterList());
          compareThrows(beforeMethod.getThrowsList(), afterMethod.getThrowsList(), afterMethod);

          if (shouldCompareCodeBlocks()) {
            final PsiCodeBlock beforeMethodBody = beforeMethod.getBody();
            final PsiCodeBlock afterMethodBody = afterMethod.getBody();
            if (null != beforeMethodBody && null != afterMethodBody) {

              boolean codeBlocksAreEqual = beforeMethodBody.textMatches(afterMethodBody);
              if (!codeBlocksAreEqual) {
                String text1 = beforeMethodBody.getText().replaceAll("\\s+", "");
                String text2 = afterMethodBody.getText().replaceAll("\\s+", "");
                assertEquals("Methods not equal, Method: (" + afterMethod.getName() + ") Class:" + afterClass.getName(), text2, text1);
              }
            } else {
              if (null != afterMethodBody) {
                fail("MethodCodeBlocks is null: Method: (" + beforeMethod.getName() + ") Class:" + beforeClass.getName());
              }
            }
          }

          compared = true;
        }
      }
      assertTrue("Method names are not equal, Method: (" + afterMethod.getName() + ") not found in class : " + beforeClass.getName(), compared);
    }
  }

  private void compareThrows(PsiReferenceList beforeThrows, PsiReferenceList afterThrows, PsiMethod psiMethod) {
    PsiClassType[] beforeTypes = beforeThrows.getReferencedTypes();
    PsiClassType[] afterTypes = afterThrows.getReferencedTypes();

    assertEquals("Throws counts are different for Method :" + psiMethod.getName(), beforeTypes.length, afterTypes.length);
    for (PsiClassType beforeType : beforeTypes) {
      boolean found = false;
      for (PsiClassType afterType : afterTypes) {
        if (beforeType.equals(afterType)) {
          found = true;
          break;
        }
      }
      assertTrue("Expected throw: " + beforeType.getClassName() + " not found on " + psiMethod.getName(), found);
    }
  }

  private void compareConstructors(PsiClass intellij, PsiClass theirs) {
    PsiMethod[] intellijConstructors = intellij.getConstructors();
    PsiMethod[] theirsConstructors = theirs.getConstructors();

    LOG.debug("IntelliJ constructors for class " + intellij.getName() + ": " + Arrays.toString(intellijConstructors));
    LOG.debug("Theirs constructors for class " + theirs.getName() + ": " + Arrays.toString(theirsConstructors));

    assertEquals("Constructor counts are different for Class: " + intellij.getName(), theirsConstructors.length, intellijConstructors.length);

    for (PsiMethod theirsConstructor : theirsConstructors) {
      boolean compared = false;
      final PsiModifierList theirsFieldModifierList = theirsConstructor.getModifierList();
      for (PsiMethod intellijConstructor : intellijConstructors) {
        if (theirsConstructor.getName().equals(intellijConstructor.getName()) &&
            theirsConstructor.getParameterList().getParametersCount() == intellijConstructor.getParameterList().getParametersCount()) {
          PsiModifierList intellijConstructorModifierList = intellijConstructor.getModifierList();

          compareModifiers(intellijConstructorModifierList, theirsFieldModifierList);
          compareType(intellijConstructor.getReturnType(), theirsConstructor.getReturnType(), theirsConstructor);
          compareParams(intellijConstructor.getParameterList(), theirsConstructor.getParameterList());

          compared = true;
          break;
        }

      }
      assertTrue("Constructor names are not equal, Method: (" + theirsConstructor.getName() + ") not found in class : " + intellij.getName(), compared);
    }
  }

  private void compareContainingClasses(PsiClass intellij, PsiClass theirs) {
    PsiClass intellijContainingClass = intellij.getContainingClass();
    PsiClass theirsContainingClass = theirs.getContainingClass();

    String intellijContainingClassName = intellijContainingClass == null ? null : intellijContainingClass.toString();
    String theirsContainingClassName = theirsContainingClass == null ? null : theirsContainingClass.toString();

    LOG.debug("IntelliJ containing class for class " + intellij.getName() + ": " + intellijContainingClassName);
    LOG.debug("Theirs containing class for class " + theirs.getName() + ": " + theirsContainingClassName);

    assertEquals("Containing classes different for class: " + intellij.getName(), intellijContainingClassName, theirsContainingClassName);
  }

  private void compareInnerClasses(PsiClass intellij, PsiClass theirs) {
    PsiClass[] intellijClasses = intellij.getInnerClasses();
    PsiClass[] theirsClasses = theirs.getInnerClasses();

    LOG.debug("IntelliJ inner classes for class " + intellij.getName() + ": " + Arrays.toString(intellijClasses));
    LOG.debug("Theirs inner classes for class " + theirs.getName() + ": " + Arrays.toString(theirsClasses));

    compareClasses(intellijClasses, theirsClasses);
  }

  private void compareParams(PsiParameterList intellij, PsiParameterList theirs) {
    assertEquals(theirs.getParametersCount(), intellij.getParametersCount());

    PsiParameter[] intellijParameters = intellij.getParameters();
    PsiParameter[] theirsParameters = theirs.getParameters();
    for (int i = 0; i < intellijParameters.length; i++) {
      PsiParameter intellijParameter = intellijParameters[i];
      PsiParameter theirsParameter = theirsParameters[i];

      compareType(intellijParameter.getType(), theirsParameter.getType(), theirsParameter);
    }
  }

  private static class QualifiedNameFunction implements Function<PsiAnnotation, String> {
    @Override
    public String apply(PsiAnnotation psiAnnotation) {
      return psiAnnotation.getQualifiedName();
    }
  }
}
TOP

Related Classes of de.plushnikov.lombok.LombokParsingTestCase

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.