@Override
  protected void check(@NotNull final GrControlFlowOwner owner, @NotNull final ProblemsHolder problemsHolder) {
    final Instruction[] flow = owner.getControlFlow();
    final ReachingDefinitionsDfaInstance dfaInstance = new ReachingDefinitionsDfaInstance();
    final ReachingDefinitionsSemilattice lattice = new ReachingDefinitionsSemilattice();
    final DFAEngine<DefinitionMap> engine = new DFAEngine<>(flow, dfaInstance, lattice);
    final List<DefinitionMap> dfaResult = engine.performDFAWithTimeout();
    if (dfaResult == null) {
      return;
    }

    final IntSet unusedDefs = new IntOpenHashSet();
    for (Instruction instruction : flow) {
      if (instruction instanceof ReadWriteVariableInstruction && ((ReadWriteVariableInstruction) instruction).isWrite()) {
        unusedDefs.add(instruction.num());
      }
    }

    for (int i = 0; i < dfaResult.size(); i++) {
      final Instruction instruction = flow[i];
      if (instruction instanceof ReadWriteVariableInstruction varInst) {
        if (!varInst.isWrite()) {
          final int descriptor = varInst.getDescriptor();
          DefinitionMap e = dfaResult.get(i);
          if (e == null) {
            continue;
          }
          e.forEachValue(reaching -> {
            reaching.forEach((IntConsumer)defNum -> {
              final int defDescriptor = ((ReadWriteVariableInstruction)flow[defNum]).getDescriptor();
              if (descriptor == defDescriptor) {
                unusedDefs.remove(defNum);
              }
            });
          });
        }
      }
    }

    final Set<PsiElement> checked = new HashSet<>();

    unusedDefs.forEach((IntConsumer)num -> {
      final ReadWriteVariableInstruction instruction = (ReadWriteVariableInstruction)flow[num];
      final PsiElement element = instruction.getElement();
      process(element, checked, problemsHolder, GroovyBundle.message("unused.assignment.tooltip"));
    });

    owner.acceptChildren(new PsiRecursiveElementWalkingVisitor() {
      @Override
      public void visitElement(@NotNull PsiElement element) {
        if (element instanceof GrControlFlowOwner) {
          // don't go deeper
        }
        else if (element instanceof GrVariable variable && !(element instanceof GrField)) {
          if (checked.contains(variable) || variable.getInitializerGroovy() != null) return;
          if (ReferencesSearch.search(variable, variable.getUseScope()).findFirst() == null) {
            process(variable, checked, problemsHolder, GroovyBundle.message("unused.variable"));
          }
        }
        else {
          super.visitElement(element);
        }
      }
    });
  }
@Override
  protected void check(@NotNull final GrControlFlowOwner owner, @NotNull final ProblemsHolder problemsHolder)