public void build(CompileScope scope, boolean forceCleanCaches) throws RebuildRequestedException {
    Tracer.Span rebuildRequiredSpan = Tracer.start("IncProjectBuilder.checkRebuildRequired");
    checkRebuildRequired(scope);
    rebuildRequiredSpan.complete();

    final LowMemoryWatcher memWatcher = LowMemoryWatcher.register(() -> {
      JavacMain.clearCompilerZipFileCache();
      myProjectDescriptor.dataManager.flush(false);
      myProjectDescriptor.getProjectStamps().getStampStorage().force();
    });

    final CleanupTempDirectoryExtension cleaner = CleanupTempDirectoryExtension.getInstance();
    final Future<Void> cleanupTask = cleaner != null && cleaner.getCleanupTask() != null? cleaner.getCleanupTask() : startTempDirectoryCleanupTask(myProjectDescriptor);
    if (cleanupTask != null) {
      myAsyncTasks.add(cleanupTask);
    }

    CompileContextImpl context = null;
    BuildTargetSourcesState sourcesState = null;
    try {
      context = createContext(scope);
      sourcesState = new BuildTargetSourcesState(context);
      // Clear source state report if force clean or rebuild
      if (forceCleanCaches || context.isProjectRebuild()) {
        sourcesState.clearSourcesState();
      }
      Tracer.Span buildSpan = Tracer.start("IncProjectBuilder.runBuild");
      runBuild(context, forceCleanCaches);
      buildSpan.complete();
      myProjectDescriptor.dataManager.saveVersion();
      myProjectDescriptor.dataManager.reportUnhandledRelativizerPaths();
      sourcesState.reportSourcesState();
      reportRebuiltModules(context);
      reportUnprocessedChanges(context);
    }
    catch (StopBuildException e) {
      reportRebuiltModules(context);
      reportUnprocessedChanges(context);
      // If build was canceled for some reasons e.g., compilation error we should report built modules
      sourcesState.reportSourcesState();
      // some builder decided to stop the build
      // report optional progress message if any
      final String msg = e.getMessage();
      if (!StringUtil.isEmptyOrSpaces(msg)) {
        myMessageDispatcher.processMessage(new ProgressMessage(msg));
      }
    }
    catch (BuildDataCorruptedException e) {
      LOG.info(e);
      requestRebuild(e, e);
    }
    catch (ProjectBuildException e) {
      LOG.info(e);
      final Throwable cause = e.getCause();
      if (cause instanceof IOException ||
          cause instanceof BuildDataCorruptedException ||
          (cause instanceof RuntimeException && cause.getCause() instanceof IOException)) {
        requestRebuild(e, cause);
      }
      else {
        // should stop the build with error
        final String errMessage = e.getMessage();
        final CompilerMessage msg;
        if (StringUtil.isEmptyOrSpaces(errMessage)) {
          msg = new CompilerMessage("", cause != null ? cause : e);
        }
        else {
          final String causeMessage = cause != null ? cause.getMessage() : "";
          msg = new CompilerMessage("", BuildMessage.Kind.ERROR, StringUtil.isEmptyOrSpaces(causeMessage) || errMessage.trim().endsWith(causeMessage)
                                                                 ? errMessage
                                                                 : errMessage + ": " + causeMessage);
        }
        myMessageDispatcher.processMessage(msg);
      }
    }
    finally {
      Tracer.Span finishingCompilationSpan = Tracer.start("finishing compilation");
      memWatcher.stop();
      flushContext(context);
      // wait for async tasks
      final CanceledStatus status = context == null ? CanceledStatus.NULL : context.getCancelStatus();
      synchronized (myAsyncTasks) {
        for (Future<?> task : myAsyncTasks) {
          if (status.isCanceled()) {
            break;
          }
          waitForTask(status, task);
        }
      }
      finishingCompilationSpan.complete();
    }
  }
public void build(CompileScope scope, boolean forceCleanCaches)