### Question:
RangeConverter { @Nullable public static TextRange parse(@Nullable String value) { if (value == null) { return null; } String[] values = value.split(":", 4); if (values.length != 4) { throw new IllegalArgumentException("Invalid TextRange '" + value + "'"); } int startLine = Integer.parseInt(values[0]); int startLineOffset = Integer.parseInt(values[1]); int endLine = Integer.parseInt(values[2]); int endLineOffset = Integer.parseInt(values[3]); return new TextRangeImpl(startLine, startLineOffset, endLine, endLineOffset); } private  RangeConverter(); @Nullable static String format(@Nullable TextRange range); @Nullable static TextRange parse(@Nullable String value); @Nullable static String tokenReference(@Nullable Token token); @Nullable static Token resolveToken(TreeMetaDataProvider metaDataProvider, @Nullable String tokenReference); static String metaDataReference(Tree tree); static TreeMetaData resolveMetaData(TreeMetaDataProvider metaDataProvider, String metaDataReference); @Nullable static String treeReference(@Nullable Tree tree); @Nullable static T resolveNullableTree(Tree parent, @Nullable String treeReference, Class<T> childClass);  }### Answer:
@Test public void parse() { TextRange range = RangeConverter.parse("3:7:4:12"); assertThat(range.start().line()).isEqualTo(3); assertThat(range.start().lineOffset()).isEqualTo(7); assertThat(range.end().line()).isEqualTo(4); assertThat(range.end().lineOffset()).isEqualTo(12); }
@Test public void parse_null_string() { assertThat(RangeConverter.parse(null)).isNull(); }
@Test public void parse_invalid_string() { exceptionRule.expect(IllegalArgumentException.class); exceptionRule.expectMessage("Invalid TextRange '12345'"); RangeConverter.parse("12345"); }