private void analyzeDfaWithNestedClosures(
      PsiElement scope,
      ProblemsHolder holder,
      StandardDataFlowRunner dfaRunner,
      Collection<DfaMemoryState> initialStates) {
    final DataFlowInstructionVisitor visitor = new DataFlowInstructionVisitor(dfaRunner);
    final RunnerResult rc =
        dfaRunner.analyzeMethod(scope, visitor, IGNORE_ASSERT_STATEMENTS, initialStates);
    if (rc == RunnerResult.OK) {
      createDescription(dfaRunner, holder, visitor);

      MultiMap<PsiElement, DfaMemoryState> nestedClosures = dfaRunner.getNestedClosures();
      for (PsiElement closure : nestedClosures.keySet()) {
        analyzeDfaWithNestedClosures(closure, holder, dfaRunner, nestedClosures.get(closure));
      }
    } else if (rc == RunnerResult.TOO_COMPLEX) {
      if (scope.getParent() instanceof PsiMethod) {
        PsiMethod method = (PsiMethod) scope.getParent();
        final PsiIdentifier name = method.getNameIdentifier();
        if (name != null) { // Might be null for synthetic methods like JSP page.
          holder.registerProblem(
              name,
              InspectionsBundle.message("dataflow.too.complex"),
              ProblemHighlightType.WEAK_WARNING);
        }
      }
    }
  }
 @Override
 public void visitMethod(@NotNull PsiMethod method) {
   super.visitMethod(method);
   final PsiCodeBlock body = method.getBody();
   if (body == null) {
     return;
   }
   if (method.getNameIdentifier() == null) {
     return;
   }
   final PsiMethod leastConcreteSuperMethod = getLeastConcreteSuperMethod(method);
   if (leastConcreteSuperMethod == null) {
     return;
   }
   final PsiClass objectClass = ClassUtils.findObjectClass(method);
   final PsiMethod[] superMethods = method.findSuperMethods(objectClass);
   if (superMethods.length > 0) {
     return;
   }
   if (ignoreEmptySuperMethods) {
     final PsiMethod superMethod = (PsiMethod) leastConcreteSuperMethod.getNavigationElement();
     if (MethodUtils.isTrivial(superMethod, true)) {
       return;
     }
   }
   if (onlyReportWhenAnnotated) {
     if (!AnnotationUtil.isAnnotated(leastConcreteSuperMethod, annotations)) {
       return;
     }
   }
   if (containsSuperCall(body, leastConcreteSuperMethod)) {
     return;
   }
   registerMethodError(method);
 }
 @Override
 public void visitMethod(@NotNull PsiMethod method) {
   // note: no call to super
   if (method.getNameIdentifier() == null) {
     return;
   }
   if (!method.isConstructor()) {
     return;
   }
   if (ignoreScope != Scope.NONE) {
     switch (ignoreScope.ordinal()) {
       case 3:
         if (method.hasModifierProperty(PsiModifier.PROTECTED)) return;
       case 2:
         if (method.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) return;
       case 1:
         if (method.hasModifierProperty(PsiModifier.PRIVATE)) return;
     }
   }
   final PsiParameterList parameterList = method.getParameterList();
   final int parametersCount = parameterList.getParametersCount();
   if (parametersCount <= getLimit()) {
     return;
   }
   registerMethodError(method, Integer.valueOf(parametersCount));
 }
 protected final void registerMethodError(@NotNull PsiMethod method, Object... infos) {
   final PsiElement nameIdentifier = method.getNameIdentifier();
   if (nameIdentifier == null) {
     registerError(method.getContainingFile(), infos);
   } else {
     registerError(nameIdentifier, infos);
   }
 }
  /**
   * Check the element. If the element is a PsiMethod, than we want to know if it's a @Provides
   * method, or a Constructor annotated w/ @Inject.
   *
   * <p>If element is a field, than we only want to see if it is annotated with @Inject.
   *
   * @return a {@link com.intellij.codeInsight.daemon.GutterIconNavigationHandler} for the
   *     appropriate type, or null if we don't care about it.
   */
  @Nullable
  @Override
  public LineMarkerInfo getLineMarkerInfo(@NotNull final PsiElement element) {
    // Check methods first (includes constructors).
    if (element instanceof PsiMethod) {
      PsiMethod methodElement = (PsiMethod) element;

      // @Provides
      if (PsiConsultantImpl.hasAnnotation(element, CLASS_PROVIDES)) {
        PsiTypeElement returnTypeElement = methodElement.getReturnTypeElement();
        if (returnTypeElement != null) {
          return new LineMarkerInfo<PsiElement>(
              element,
              returnTypeElement.getTextRange(),
              ICON,
              UPDATE_ALL,
              null,
              new ProvidesToInjectHandler(),
              LEFT);
        }
      }

      // Constructor injection.
      if (methodElement.isConstructor() && PsiConsultantImpl.hasAnnotation(element, CLASS_INJECT)) {
        PsiIdentifier nameIdentifier = methodElement.getNameIdentifier();
        if (nameIdentifier != null) {
          return new LineMarkerInfo<PsiElement>(
              element,
              nameIdentifier.getTextRange(),
              ICON,
              UPDATE_ALL,
              null,
              new ConstructorInjectToProvidesHandler(),
              LEFT);
        }
      }

      // Not a method, is it a Field?
    } else if (element instanceof PsiField) {
      // Field injection.
      PsiField fieldElement = (PsiField) element;
      PsiTypeElement typeElement = fieldElement.getTypeElement();

      if (PsiConsultantImpl.hasAnnotation(element, CLASS_INJECT) && typeElement != null) {
        return new LineMarkerInfo<PsiElement>(
            element,
            typeElement.getTextRange(),
            ICON,
            UPDATE_ALL,
            null,
            new FieldInjectToProvidesHandler(),
            LEFT);
      }
    }

    return null;
  }
  @Override
  public CommonProblemDescriptor[] checkElement(
      @NotNull RefEntity refEntity,
      @NotNull AnalysisScope scope,
      @NotNull final InspectionManager manager,
      @NotNull final GlobalInspectionContext globalContext) {
    if (refEntity instanceof RefMethod) {
      RefMethod refMethod = (RefMethod) refEntity;
      if (!refMethod.isReferenced()) return null;
      if (hasNonInvertedCalls(refMethod)) return null;
      if (!refMethod.getSuperMethods().isEmpty()) return null;
      final PsiMethod psiMethod = (PsiMethod) refMethod.getElement();
      final PsiIdentifier psiIdentifier = psiMethod.getNameIdentifier();
      if (psiIdentifier != null) {
        final Collection<RefElement> inReferences = refMethod.getInReferences();
        if (inReferences.size() == 1) {
          final RefElement refElement = inReferences.iterator().next();
          final PsiElement usagesContainer = refElement.getElement();
          if (usagesContainer == null) return null;
          if (ReferencesSearch.search(psiMethod, new LocalSearchScope(usagesContainer))
              .forEach(
                  new Processor<PsiReference>() {
                    private final Set<PsiReference> myFoundRefs = new HashSet<>();

                    @Override
                    public boolean process(PsiReference reference) {
                      myFoundRefs.add(reference);
                      return myFoundRefs.size() < 2;
                    }
                  })) return null;
        }
        return new ProblemDescriptor[] {
          manager.createProblemDescriptor(
              psiIdentifier,
              InspectionsBundle.message("boolean.method.is.always.inverted.problem.descriptor"),
              (LocalQuickFix) getQuickFix(null),
              ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
              false)
        };
      }
    }
    return null;
  }
 @Override
 public void visitMethod(@NotNull PsiMethod method) {
   super.visitMethod(method);
   if (method.isConstructor() || method.hasModifierProperty(PsiModifier.STATIC)) {
     return;
   }
   if (method.hasModifierProperty(PsiModifier.NATIVE)
       && isInspectionEnabled("NativeMethodNamingConvention", method)) {
     return;
   }
   final PsiIdentifier nameIdentifier = method.getNameIdentifier();
   if (nameIdentifier == null) {
     return;
   }
   if (TestUtils.isRunnable(method)) {
     if (TestUtils.isJUnit4TestMethod(method)
         && isInspectionEnabled("JUnit4MethodNamingConvention", method)) {
       return;
     }
     if (TestUtils.isJUnit3TestMethod(method)
         && isInspectionEnabled("JUnit3MethodNamingConvention", method)) {
       return;
     }
   }
   if (isTestNGTestMethod(method)
       && isInspectionEnabled("TestNGMethodNamingConvention", method)) {
     return;
   }
   final String name = method.getName();
   if (isValid(name)) {
     return;
   }
   if (!isOnTheFly() && MethodUtils.hasSuper(method)) {
     return;
   }
   if (LibraryUtil.isOverrideOfLibraryMethod(method)) {
     return;
   }
   registerMethodError(method, name);
 }
  private static void processPrimaryMethod(
      JavaChangeInfo changeInfo, PsiMethod method, PsiMethod baseMethod, boolean isOriginal)
      throws IncorrectOperationException {
    PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();

    if (changeInfo.isVisibilityChanged()) {
      PsiModifierList modifierList = method.getModifierList();
      final String highestVisibility =
          isOriginal
              ? changeInfo.getNewVisibility()
              : VisibilityUtil.getHighestVisibility(
                  changeInfo.getNewVisibility(),
                  VisibilityUtil.getVisibilityModifier(modifierList));
      VisibilityUtil.setVisibility(modifierList, highestVisibility);
    }

    if (changeInfo.isNameChanged()) {
      String newName =
          baseMethod == null
              ? changeInfo.getNewName()
              : RefactoringUtil.suggestNewOverriderName(
                  method.getName(), baseMethod.getName(), changeInfo.getNewName());

      if (newName != null && !newName.equals(method.getName())) {
        final PsiIdentifier nameId = method.getNameIdentifier();
        assert nameId != null;
        nameId.replace(
            JavaPsiFacade.getInstance(method.getProject())
                .getElementFactory()
                .createIdentifier(newName));
      }
    }

    final PsiSubstitutor substitutor =
        baseMethod == null
            ? PsiSubstitutor.EMPTY
            : ChangeSignatureProcessor.calculateSubstitutor(method, baseMethod);

    if (changeInfo.isReturnTypeChanged()) {
      PsiType newTypeElement =
          changeInfo
              .getNewReturnType()
              .getType(changeInfo.getMethod().getParameterList(), method.getManager());
      final PsiType returnType = substitutor.substitute(newTypeElement);
      // don't modify return type for non-Java overriders (EJB)
      if (method.getName().equals(changeInfo.getNewName())) {
        final PsiTypeElement typeElement = method.getReturnTypeElement();
        if (typeElement != null) {
          typeElement.replace(factory.createTypeElement(returnType));
        }
      }
    }

    PsiParameterList list = method.getParameterList();
    PsiParameter[] parameters = list.getParameters();

    final JavaParameterInfo[] parameterInfos = changeInfo.getNewParameters();
    final int delta =
        baseMethod != null
            ? baseMethod.getParameterList().getParametersCount()
                - method.getParameterList().getParametersCount()
            : 0;
    PsiParameter[] newParms = new PsiParameter[Math.max(parameterInfos.length - delta, 0)];
    final String[] oldParameterNames = changeInfo.getOldParameterNames();
    final String[] oldParameterTypes = changeInfo.getOldParameterTypes();
    for (int i = 0; i < newParms.length; i++) {
      JavaParameterInfo info = parameterInfos[i];
      int index = info.getOldIndex();
      if (index >= 0) {
        PsiParameter parameter = parameters[index];
        newParms[i] = parameter;

        String oldName = oldParameterNames[index];
        if (!oldName.equals(info.getName()) && oldName.equals(parameter.getName())) {
          PsiIdentifier newIdentifier = factory.createIdentifier(info.getName());
          parameter.getNameIdentifier().replace(newIdentifier);
        }

        String oldType = oldParameterTypes[index];
        if (!oldType.equals(info.getTypeText())) {
          parameter.normalizeDeclaration();
          PsiType newType =
              substitutor.substitute(
                  info.createType(changeInfo.getMethod().getParameterList(), method.getManager()));

          parameter.getTypeElement().replace(factory.createTypeElement(newType));
        }
      } else {
        newParms[i] = createNewParameter(changeInfo, info, substitutor);
      }
    }

    resolveParameterVsFieldsConflicts(newParms, method, list, changeInfo.toRemoveParm());
    fixJavadocsForChangedMethod(method, changeInfo, newParms.length);
    if (changeInfo.isExceptionSetOrOrderChanged()) {
      final PsiClassType[] newExceptions = getPrimaryChangedExceptionInfo(changeInfo);
      fixPrimaryThrowsLists(method, newExceptions);
    }
  }
  @Override
  public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
    if (!MinecraftSettings.Companion.getInstance().isShowEventListenerGutterIcons()) {
      return;
    }

    // Since we want to line up with the method declaration, not the annotation
    // declaration, we need to target identifiers, not just PsiMethods.
    if (!(element instanceof PsiIdentifier && (element.getParent() instanceof PsiMethod))) {
      return;
    }
    // The PsiIdentifier is going to be a method of course!
    PsiMethod method = (PsiMethod) element.getParent();
    if (method.hasModifierProperty(PsiModifier.ABSTRACT)) {
      // I don't think any implementation allows for abstract
      return;
    }
    PsiModifierList modifierList = method.getModifierList();
    Module module = ModuleUtilCore.findModuleForPsiElement(element);
    if (module == null) {
      return;
    }
    MinecraftModule instance = MinecraftModule.getInstance(module);
    if (instance == null) {
      return;
    }
    // Since each platform has their own valid listener annotations,
    // some platforms may have multiple allowed annotations for various cases
    final Collection<AbstractModuleType<?>> moduleTypes = instance.getTypes();
    boolean contains = false;
    for (AbstractModuleType<?> moduleType : moduleTypes) {
      final List<String> listenerAnnotations = moduleType.getListenerAnnotations();
      for (String listenerAnnotation : listenerAnnotations) {
        if (modifierList.findAnnotation(listenerAnnotation) != null) {
          contains = true;
          break;
        }
      }
    }
    if (!contains) {
      return;
    }

    final PsiParameter[] parameters = method.getParameterList().getParameters();
    if (parameters.length < 1) {
      return;
    }
    final PsiParameter eventParameter = parameters[0];
    if (eventParameter == null) {
      // Listeners must have at least a single parameter
      return;
    }
    // Get the type of the parameter so we can start resolving it
    PsiTypeElement psiEventElement = eventParameter.getTypeElement();
    if (psiEventElement == null) {
      return;
    }
    final PsiType type = psiEventElement.getType();
    // Validate that it is a class reference type, I don't know if this will work with
    // other JVM languages such as Kotlin or Scala, but it might!
    if (!(type instanceof PsiClassReferenceType)) {
      return;
    }
    // And again, make sure that we can at least resolve the type, otherwise it's not a valid
    // class reference.
    final PsiClass eventClass = ((PsiClassReferenceType) type).resolve();
    if (eventClass == null) {
      return;
    }

    if (instance.isEventClassValid(eventClass, method)) {
      return;
    }

    if (!instance.isStaticListenerSupported(eventClass, method)
        && method.hasModifierProperty(PsiModifier.STATIC)) {
      if (method.getNameIdentifier() != null) {
        holder.createErrorAnnotation(
            method.getNameIdentifier(), "Event listener method must not be static");
      }
    }

    if (!isSuperEventListenerAllowed(eventClass, method, instance)) {
      holder.createErrorAnnotation(
          eventParameter, instance.writeErrorMessageForEvent(eventClass, method));
    }
  }