static @Nullable
    Context from(@NotNull PsiTryStatement tryStatement) {
      PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock();
      if (finallyBlock == null) return null;
      PsiCodeBlock tryBlock = tryStatement.getTryBlock();
      if (tryBlock == null) return null;
      PsiStatement[] tryStatements = tryBlock.getStatements();
      PsiStatement[] finallyStatements = finallyBlock.getStatements();
      BitSet closedVariableStatementIndices = new BitSet(finallyStatements.length);
      Set<PsiVariable> collectedVariables = new HashSet<>();
      for (int i = 0, length = finallyStatements.length; i < length; i++) {
        PsiStatement statement = finallyStatements[i];
        closedVariableStatementIndices.set(i, findAutoCloseableVariables(statement, collectedVariables));
      }
      if (collectedVariables.isEmpty()) return null;
      if (resourceVariablesUsedInFinally(finallyStatements, closedVariableStatementIndices, collectedVariables)) return null;
      if (resourceVariableUsedInCatches(tryStatement, collectedVariables)) return null;

      List<ResourceVariable> resourceVariables = new ArrayList<>();
      List<PsiStatement> statementsToDelete = new ArrayList<>();
      IntList initializerPositions = new IntArrayList();
      for (PsiVariable resourceVariable : collectedVariables) {
        boolean variableUsedOutsideTry = isVariableUsedOutsideContext(resourceVariable, tryStatement);
        if (!PsiUtil.isAvailable(JavaFeature.REFS_AS_RESOURCE, finallyBlock) && variableUsedOutsideTry) return null;
        if (!variableUsedOutsideTry && resourceVariable instanceof PsiLocalVariable) {
          PsiExpression initializer = resourceVariable.getInitializer();
          boolean hasNonNullInitializer = initializer != null && !PsiTypes.nullType().equals(initializer.getType());
          if (!hasNonNullInitializer) {
            int assignmentStatementIndex = findInitialization(tryStatements, resourceVariable);
            if (assignmentStatementIndex == -1) return null;
            initializerPositions.add(assignmentStatementIndex);
            PsiExpressionStatement assignmentStatement = (PsiExpressionStatement)tryStatements[assignmentStatementIndex];
            PsiExpression expression = assignmentStatement.getExpression();
            PsiAssignmentExpression assignment = tryCast(expression, PsiAssignmentExpression.class);
            if (assignment == null) return null;
            initializer = assignment.getRExpression();
            if (initializer == null) return null;
            statementsToDelete.add(tryStatements[assignmentStatementIndex]);
          }
          else {
            if (VariableAccessUtils.variableIsAssigned(resourceVariable, tryBlock)) return null;
          }
          resourceVariables.add(new ResourceVariable(initializer, false, resourceVariable));
        }
        else if (((resourceVariable instanceof PsiLocalVariable && resourceVariable.getInitializer() != null) ||
                  resourceVariable instanceof PsiParameter) && FinalUtils.canBeFinal(resourceVariable)) {
          resourceVariables.add(new ResourceVariable(null, true, resourceVariable));
        }
        else {
          return null;
        }
      }
      for (int i = 0; i < finallyStatements.length; i++) {
        if (closedVariableStatementIndices.get(i)) {
          statementsToDelete.add(finallyStatements[i]);
        }
      }
      if (!noStatementsBetweenVariableDeclarations(collectedVariables) || !initializersAreAtTheBeginning(initializerPositions)) {
        return null;
      }

      resourceVariables.sort(Comparator.comparing(o -> o.getInitializedElement(), PsiElementOrderComparator.getInstance()));
      ResourceVariable lastNonTryVar = ContainerUtil.findLast(resourceVariables,
                                                              r -> !PsiTreeUtil.isAncestor(tryStatement, r.myVariable, false));
      if (lastNonTryVar != null) {
        PsiVariable variable = lastNonTryVar.myVariable;
        PsiStatement statement = PsiTreeUtil.getParentOfType(variable, PsiStatement.class);
        List<PsiStatement> statements = collectStatementsBetween(statement, tryStatement);
        boolean varUsedNotInTry = StreamEx.of(statements)
          .flatMap(stmt -> StreamEx.ofTree((PsiElement)stmt, e -> StreamEx.of(e.getChildren())))
          .select(PsiLocalVariable.class)
          .anyMatch(variable1 -> isVariableUsedOutsideContext(variable1, tryStatement));
        if (varUsedNotInTry) return null;
      }
      return new Context(resourceVariables, new HashSet<>(statementsToDelete));
    }
static @Nullable
    Context from(@NotNull PsiTryStatement tryStatement)