private static boolean updateMappings(CompileContext context,
                                        final Mappings delta,
                                        DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
                                        ModuleChunk chunk,
                                        Collection<? extends File> filesToCompile,
                                        Collection<? extends File> successfullyCompiled,
                                        final CompilationRound markDirtyRound,
                                        @Nullable FileFilter skipMarkingDirtyFilter) throws IOException {
    try {
      boolean performIntegrate = true;
      boolean additionalPassRequired = false;

      final Set<String> removedPaths = getRemovedPaths(chunk, dirtyFilesHolder);

      final Mappings globalMappings = context.getProjectDescriptor().dataManager.getMappings();

      final boolean errorsDetected = Utils.errorsDetected(context);
      if (!isForcedRecompilationAllJavaModules(context)) {
        if (context.shouldDifferentiate(chunk)) {
          context.processMessage(new ProgressMessage(JpsBuildBundle.message("progress.message.checking.dependencies.0", chunk.getPresentableShortName())));
          final Set<File> allCompiledFiles = getFilesContainer(context, ALL_COMPILED_FILES_KEY);
          final Set<File> allAffectedFiles = getFilesContainer(context, ALL_AFFECTED_FILES_KEY);

          // mark as affected all files that were dirty before compilation
          allAffectedFiles.addAll(filesToCompile);
          // accumulate all successfully compiled in this round
          allCompiledFiles.addAll(successfullyCompiled);
          // unmark as affected all successfully compiled
          allAffectedFiles.removeAll(successfullyCompiled);

          final Set<File> affectedBeforeDif = FileCollectionFactory.createCanonicalFileSet();
          affectedBeforeDif.addAll(allAffectedFiles);

          final Set<File> compiledWithErrors = getFilesContainer(context, COMPILED_WITH_ERRORS_KEY);
          COMPILED_WITH_ERRORS_KEY.set(context, null);

          final ModulesBasedFileFilter moduleBasedFilter = new ModulesBasedFileFilter(context, chunk);
          final boolean incremental = globalMappings.differentiateOnIncrementalMake(
            delta, removedPaths, filesToCompile, compiledWithErrors, allCompiledFiles, allAffectedFiles, moduleBasedFilter
          );

          if (LOG.isDebugEnabled()) {
            LOG.debug("Differentiate Results:");
            LOG.debug("   Compiled Files:");
            for (final File c : allCompiledFiles) {
              LOG.debug("      " + c.getAbsolutePath());
            }
            LOG.debug("   Affected Files:");
            for (final File c : allAffectedFiles) {
              LOG.debug("      " + c.getAbsolutePath());
            }
            LOG.debug("End Of Differentiate Results.");
          }

          final boolean compilingIncrementally = isCompileJavaIncrementally(context);
          if (incremental) {
            final Set<File> newlyAffectedFiles = new HashSet<>(allAffectedFiles);
            newlyAffectedFiles.removeAll(affectedBeforeDif);

            final String infoMessage = JpsBuildBundle.message("progress.message.dependency.analysis.found.0.affected.files", newlyAffectedFiles.size());
            LOG.info(infoMessage);
            context.processMessage(new ProgressMessage(infoMessage));

            removeFilesAcceptedByFilter(newlyAffectedFiles, skipMarkingDirtyFilter);

            if (!newlyAffectedFiles.isEmpty()) {

              if (LOG.isDebugEnabled()) {
                for (File file : newlyAffectedFiles) {
                  LOG.debug("affected file: " + file.getPath());
                }
                final List<Pair<File, JpsModule>> wrongFiles =
                  checkAffectedFilesInCorrectModules(context, newlyAffectedFiles, moduleBasedFilter);
                if (!wrongFiles.isEmpty()) {
                  LOG.debug("Wrong affected files for module chunk " + chunk.getName() + ": ");
                  for (Pair<File, JpsModule> pair : wrongFiles) {
                    final String name = pair.second != null ? pair.second.getName() : "null";
                    LOG.debug("\t[" + name + "] " + pair.first.getPath());
                  }
                }
              }

              Set<ModuleBuildTarget> targetsToMark = null;
              final JavaModuleIndex moduleIndex = getJavaModuleIndex(context);
              for (File file : newlyAffectedFiles) {
                if (MODULE_INFO_FILE.equals(file.getName())) {
                  final JavaSourceRootDescriptor rootDescr = context.getProjectDescriptor().getBuildRootIndex().findJavaRootDescriptor(context, file);
                  if (rootDescr != null) {
                    final ModuleBuildTarget target = rootDescr.getTarget();
                    final File targetModuleInfo = moduleIndex.getModuleInfoFile(target.getModule(), target.isTests());
                    if (FileUtil.filesEqual(targetModuleInfo, file)) {
                      if (targetsToMark == null) {
                        targetsToMark = new HashSet<>(); // lazy init
                      }
                      targetsToMark.add(target);
                    }
                  }
                }
                else {
                  FSOperations.markDirtyIfNotDeleted(context, markDirtyRound, file);
                }
              }

              boolean currentChunkAfected = false;
              if (targetsToMark != null) {
                for (ModuleBuildTarget target : targetsToMark) {
                  if (chunk.getTargets().contains(target)) {
                    currentChunkAfected = true;
                  }
                  else {
                    FSOperations.markDirty(context, markDirtyRound, target, null);
                  }
                }
                if (currentChunkAfected) {
                  if (compilingIncrementally) {
                    // turn on non-incremental mode for targets from the current chunk, if at least one of them was affected.
                    for (ModuleBuildTarget target : chunk.getTargets()) {
                      context.markNonIncremental(target);
                    }
                  }
                  FSOperations.markDirty(context, markDirtyRound, chunk, null);
                }
              }
              additionalPassRequired = compilingIncrementally && (currentChunkAfected || moduleBasedFilter.containsFilesFromCurrentTargetChunk(newlyAffectedFiles));
            }
          }
          else {
            // non-incremental mode
            final String messageText = JpsBuildBundle.message("progress.message.marking.0.and.direct.dependants.for.recompilation", chunk.getPresentableShortName());
            LOG.info("Non-incremental mode: " + messageText);
            context.processMessage(new ProgressMessage(messageText));

            final boolean alreadyMarkedDirty = FSOperations.isMarkedDirty(context, chunk);
            additionalPassRequired = compilingIncrementally && !alreadyMarkedDirty;

            if (alreadyMarkedDirty) {
              // need this to make sure changes data stored in Delta is complete
              globalMappings.differentiateOnNonIncrementalMake(delta, removedPaths, filesToCompile);
            }
            else {
              performIntegrate = false;
            }

            FileFilter toBeMarkedFilter = skipMarkingDirtyFilter == null ? null : new NegationFileFilter(skipMarkingDirtyFilter);
            FSOperations.markDirtyRecursively(context, markDirtyRound, chunk, toBeMarkedFilter);
          }
        }
        else {
          if (!errorsDetected) { // makes sense only if we are going to integrate changes
            globalMappings.differentiateOnNonIncrementalMake(delta, removedPaths, filesToCompile);
          }
        }
      }
      else {
        if (!errorsDetected) { // makes sense only if we are going to integrate changes
          globalMappings.differentiateOnRebuild(delta);
        }
      }

      if (errorsDetected) {
        // important: perform dependency analysis and mark found dependencies even if there were errors during the first phase of make.
        // Integration of changes should happen only if the corresponding phase of make succeeds
        // In case of errors this wil ensure that all dependencies marked after the first phase
        // will be compiled during the first phase of the next make
        return false;
      }

      if (performIntegrate) {
        context.processMessage(new ProgressMessage(JpsBuildBundle.message("progress.message.updating.dependency.information.0", chunk.getPresentableShortName())));
        globalMappings.integrate(delta);
      }

      return additionalPassRequired;
    }
    catch (BuildDataCorruptedException e) {
      throw e.getCause();
    }
    finally {
      context.processMessage(new ProgressMessage("")); // clean progress messages
    }
  }
private static boolean updateMappings(CompileContext context,
                                        final Mappings delta,
                                        DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
                                        ModuleChunk chunk,
                                        Collection<? extends File> filesToCompile,
                                        Collection<? extends File> successfullyCompiled,
                                        final CompilationRound markDirtyRound,
                                        @Nullable FileFilter skipMarkingDirtyFilter)