docs: public void read(@WillClose InputStream inputStream) throws IOException {
          BufferedReader reader = new BufferedReader(Util.getReader(inputStream));
  
          int lineNumber = 0;
          try {
              String line;
              int lparen;
              String version;
  
              while ((line = reader.readLine()) != null) {
                  ++lineNumber;
  
                  if (lineNumber == 1) {
                      if (DEBUG) {
                          System.out.println("First line: " + line);
                      }
                      // Try to parse the version number string from the first
                      // line.
                      // null means that the line does not appear to be a version
                      // number.
                      version = parseVersionNumber(line);
                      if (version != null) {
                          // Check to see if version is supported.
                          // Only 1.0 supported for now.
                          if (!"1.0".equals(version)) {
                              throw new IOException("Unsupported sourceInfo version " + version);
                          }
  
                          // Version looks good. Skip to next line of file.
                          continue;
                      }
                  }
  
                  StringTokenizer tokenizer = new StringTokenizer(line, ",");
  
                  String className = tokenizer.nextToken();
                  String next = tokenizer.nextToken();
                  if (DIGITS.matcher(next).matches()) {
                      // Line number for class
                      SourceLineRange range = createRange(next, tokenizer.nextToken());
                      classLineMap.put(className, range);
                      if (DEBUG) {
                          System.out.println("class:" + className + "," + range);
                      }
                  } else if ((lparen = next.indexOf('(')) >= 0) {
                      // Line number for method
                      String methodName = next.substring(0, lparen);
                      String methodSignature = next.substring(lparen);
  
                      if ("init^".equals(methodName)) {
                          methodName = "<init>";
                      } else if ("clinit^".equals(methodName)) {
                          methodName = "<clinit>";
                      }
  
                      SourceLineRange range = createRange(tokenizer.nextToken(), tokenizer.nextToken());
                      methodLineMap.put(new MethodDescriptor(className, methodName, methodSignature), range);
                      if (DEBUG) {
                          System.out.println("method:" + methodName + methodSignature + "," + range);
                      }
                  } else {
                      // Line number for field
                      String fieldName = next;
                      SourceLineRange range = createRange(tokenizer.nextToken(), tokenizer.nextToken());
                      fieldLineMap.put(new FieldDescriptor(className, fieldName), range);
                      if (DEBUG) {
                          System.out.println("field:" + className + "," + fieldName + "," + range);
                      }
                  }
  
                  // Note: we could complain if there are more tokens,
                  // but instead we'll just ignore them.
              }
          } catch (NoSuchElementException e) {
              IOException ioe = new IOException("Invalid syntax in source info file at line " + lineNumber);
              ioe.initCause(e);
              throw ioe;
          } finally {
              try {
                  reader.close();
              } catch (IOException e) {
                  // ignore
              }
          }
      }