private function process()
 {
     $whitespace_mode = $this->whitespaceMode;
     $changeset = $this->changeset;
     $ignore_all = $whitespace_mode == self::WHITESPACE_IGNORE_MOST || $whitespace_mode == self::WHITESPACE_IGNORE_ALL;
     $force_ignore = $whitespace_mode == self::WHITESPACE_IGNORE_ALL;
     if (!$force_ignore) {
         if ($ignore_all && $changeset->getWhitespaceMatters()) {
             $ignore_all = false;
         }
     }
     // The "ignore all whitespace" algorithm depends on rediffing the
     // files, and we currently need complete representations of both
     // files to do anything reasonable. If we only have parts of the files,
     // don't use the "ignore all" algorithm.
     if ($ignore_all) {
         $hunks = $changeset->getHunks();
         if (count($hunks) !== 1) {
             $ignore_all = false;
         } else {
             $first_hunk = reset($hunks);
             if ($first_hunk->getOldOffset() != 1 || $first_hunk->getNewOffset() != 1) {
                 $ignore_all = false;
             }
         }
     }
     if ($ignore_all) {
         $old_file = $changeset->makeOldFile();
         $new_file = $changeset->makeNewFile();
         if ($old_file == $new_file) {
             // If the old and new files are exactly identical, the synthetic
             // diff below will give us nonsense and whitespace modes are
             // irrelevant anyway. This occurs when you, e.g., copy a file onto
             // itself in Subversion (see T271).
             $ignore_all = false;
         }
     }
     $hunk_parser = new DifferentialHunkParser();
     $hunk_parser->setWhitespaceMode($whitespace_mode);
     $hunk_parser->parseHunksForLineData($changeset->getHunks());
     // Depending on the whitespace mode, we may need to compute a different
     // set of changes than the set of changes in the hunk data (specificaly,
     // we might want to consider changed lines which have only whitespace
     // changes as unchanged).
     if ($ignore_all) {
         $engine = new PhabricatorDifferenceEngine();
         $engine->setIgnoreWhitespace(true);
         $no_whitespace_changeset = $engine->generateChangesetFromFileContent($old_file, $new_file);
         $type_parser = new DifferentialHunkParser();
         $type_parser->parseHunksForLineData($no_whitespace_changeset->getHunks());
         $hunk_parser->setOldLineTypeMap($type_parser->getOldLineTypeMap());
         $hunk_parser->setNewLineTypeMap($type_parser->getNewLineTypeMap());
     }
     $hunk_parser->reparseHunksForSpecialAttributes();
     $unchanged = false;
     if (!$hunk_parser->getHasAnyChanges()) {
         $filetype = $this->changeset->getFileType();
         if ($filetype == DifferentialChangeType::FILE_TEXT || $filetype == DifferentialChangeType::FILE_SYMLINK) {
             $unchanged = true;
         }
     }
     $moveaway = false;
     $changetype = $this->changeset->getChangeType();
     if ($changetype == DifferentialChangeType::TYPE_MOVE_AWAY) {
         $moveaway = true;
     }
     $this->setSpecialAttributes(array(self::ATTR_UNCHANGED => $unchanged, self::ATTR_DELETED => $hunk_parser->getIsDeleted(), self::ATTR_WHITELINES => !$hunk_parser->getHasTextChanges(), self::ATTR_MOVEAWAY => $moveaway));
     $lines_context = $this->getLinesOfContext();
     $hunk_parser->generateIntraLineDiffs();
     $hunk_parser->generateVisibileLinesMask($lines_context);
     $this->setOldLines($hunk_parser->getOldLines());
     $this->setNewLines($hunk_parser->getNewLines());
     $this->setIntraLineDiffs($hunk_parser->getIntraLineDiffs());
     $this->setVisibileLinesMask($hunk_parser->getVisibleLinesMask());
     $this->hunkStartLines = $hunk_parser->getHunkStartLines($changeset->getHunks());
     $new_corpus = $hunk_parser->getNewCorpus();
     $new_corpus_block = implode('', $new_corpus);
     $this->markGenerated($new_corpus_block);
     if ($this->isTopLevel && !$this->comments && ($this->isGenerated() || $this->isUnchanged() || $this->isDeleted())) {
         return;
     }
     $old_corpus = $hunk_parser->getOldCorpus();
     $old_corpus_block = implode('', $old_corpus);
     $old_future = $this->getHighlightFuture($old_corpus_block);
     $new_future = $this->getHighlightFuture($new_corpus_block);
     $futures = array('old' => $old_future, 'new' => $new_future);
     $corpus_blocks = array('old' => $old_corpus_block, 'new' => $new_corpus_block);
     $this->highlightErrors = false;
     foreach (new FutureIterator($futures) as $key => $future) {
         try {
             try {
                 $highlighted = $future->resolve();
             } catch (PhutilSyntaxHighlighterException $ex) {
                 $this->highlightErrors = true;
                 $highlighted = id(new PhutilDefaultSyntaxHighlighter())->getHighlightFuture($corpus_blocks[$key])->resolve();
             }
             switch ($key) {
                 case 'old':
                     $this->oldRender = $this->processHighlightedSource($this->old, $highlighted);
                     break;
                 case 'new':
                     $this->newRender = $this->processHighlightedSource($this->new, $highlighted);
                     break;
             }
         } catch (Exception $ex) {
             phlog($ex);
             throw $ex;
         }
     }
     $this->applyIntraline($this->oldRender, ipull($this->intra, 0), $old_corpus);
     $this->applyIntraline($this->newRender, ipull($this->intra, 1), $new_corpus);
 }