code: public RawTextNode substring(int newId, int start, int end) {
      checkArgument(start >= 0, "start (%s) should be greater than or equal to 0", start);
      checkArgument(start < end, "start (%s) should be less that end (%s)", start, end);
      checkArgument(
          end <= rawText.length(),
          "end (%s) should be less than or equal to the length (%s)",
          end,
          rawText.length());
      if (start == 0 && end == rawText.length()) {
        return this;
      }
      String newText = rawText.substring(start, end);
      SourceOffsets newOffsets = null;
      SourceLocation newLocation = getSourceLocation();
      if (offsets != null) {
        newOffsets = offsets.substring(start, end, rawText);
        newLocation = newOffsets.getSourceLocation(getSourceLocation().getFilePath());
      }
      return new RawTextNode(newId, newText, newLocation, newOffsets);
    }
docs: Returns a new RawTextNode that represents the given {@link String#substring(int, int)} of this
  raw text node.
  
  <p>Unlike {@link String#substring(int, int)} the range must be non-empty
  
  @param newId the new node id to use
  @param start the start location
  @param end the end location