/**
   * Parse the specified source. Any exceptions thrown by the {@link DartParser} will be logged and
   * a {@link DartModelException} thrown.
   *
   * @param sourceRef the Dart source being parsed
   * @param source the source to be parsed (not <code>null</code>)
   * @param preserveComments <code>true</code> if comments are to be preserved
   * @param parseErrors a collection to which parse errors are appended or <code>null</code> if
   *     parse errors should be ignored
   * @return the parse result
   */
  public static DartUnit parseSource(
      DartSource sourceRef,
      String source,
      boolean preserveComments,
      Collection<DartCompilationError> parseErrors)
      throws DartModelException {

    long start = System.currentTimeMillis();

    ParserRunnable runnable = new ParserRunnable(sourceRef, source, preserveComments, parseErrors);
    runnable.runSafe();

    long elapsed = System.currentTimeMillis() - start;
    Instrumentation.metric("DartCompilerUtils-parseSource", elapsed).log();
    Instrumentation.operation("DartCompilerUtils-parseSource", elapsed)
        .with("sourceRef.Name", sourceRef.getName())
        .with("source", source)
        .with("parseErrors", parseErrors != null ? parseErrors.size() : 0)
        .log();

    if (runnable.exception != null) {
      throw new DartModelException(
          new CoreException(
              new Status(
                  IStatus.ERROR,
                  DartCore.PLUGIN_ID,
                  "Failed to parse " + sourceRef.getName(),
                  runnable.exception)));
    }
    return runnable.result;
  }
  /** A synchronized call to {@link DartParser#parseUnit(DartSource)} */
  public static DartUnit secureParseUnit(DartParser parser, DartSource sourceRef) {

    long start = System.currentTimeMillis();

    // All calls to DartC must be synchronized
    synchronized (compilerLock) {
      DartUnit ret = parser.parseUnit();

      long elapsed = System.currentTimeMillis() - start;
      Instrumentation.metric("DartCompilerUtils-secureParseUnit", elapsed).log();

      Instrumentation.operation("DartCompilerUtils-secureParseUnit", elapsed)
          .with("sourceRef.Name", sourceRef != null ? sourceRef.getName() : "null")
          .log();

      return ret;
    }
  }