private static @Nullable DfaValue substring(DfaCallArguments args, DfaMemoryState state, DfaValueFactory factory, PsiType stringType) {
    if (stringType == null || !stringType.equalsToText(JAVA_LANG_STRING)) return null;
    DfaValue qualifier = args.myQualifier;
    DfaValue[] arguments = args.myArguments;
    if (arguments.length < 1 || arguments.length > 2 || arguments[0] == null) return null;
    DfaValue from = arguments[0];
    DfaValue lenVal = STRING_LENGTH.createValue(factory, qualifier);
    DfaValue to = arguments.length == 1 ? lenVal : arguments[1];
    DfaValue resultLen = factory.getBinOpFactory().create(to, from, state, INT, LongRangeBinOp.MINUS);
    if (resultLen instanceof DfaBinOpValue) {
      resultLen = factory.fromDfType(state.getDfType(resultLen));
    }
    return factory.getWrapperFactory().createWrapper(typedObject(stringType, Nullability.NOT_NULL), STRING_LENGTH, resultLen);
  }
private static @Nullable DfaValue substring(DfaCallArguments args, DfaMemoryState state, DfaValueFactory factory, PsiType stringType)