/**
  * @param \PHPSemVerChecker\Registry\Registry $registryBefore
  * @param \PHPSemVerChecker\Registry\Registry $registryAfter
  * @return \PHPSemVerChecker\Report\Report
  */
 public function analyze(Registry $registryBefore, Registry $registryAfter)
 {
     $report = new Report();
     $keysBefore = array_keys($registryBefore->data['function']);
     $keysAfter = array_keys($registryAfter->data['function']);
     $added = array_diff($keysAfter, $keysBefore);
     $removed = array_diff($keysBefore, $keysAfter);
     $toVerify = array_intersect($keysBefore, $keysAfter);
     foreach ($removed as $key) {
         $fileBefore = $registryBefore->mapping['function'][$key];
         $functionBefore = $registryBefore->data['function'][$key];
         $data = new FunctionRemoved($fileBefore, $functionBefore);
         $report->addFunction($data);
     }
     foreach ($toVerify as $key) {
         $fileBefore = $registryBefore->mapping['function'][$key];
         $functionBefore = $registryBefore->data['function'][$key];
         $fileAfter = $registryAfter->mapping['function'][$key];
         $functionAfter = $registryAfter->data['function'][$key];
         // Leave non-strict comparison here
         if ($functionBefore != $functionAfter) {
             $paramsBefore = $functionBefore->params;
             $paramsAfter = $functionAfter->params;
             $signatureResult = Signature::analyze($paramsBefore, $paramsAfter);
             $changes = ['parameter_added' => FunctionParameterAdded::class, 'parameter_removed' => FunctionParameterRemoved::class, 'parameter_renamed' => FunctionParameterNameChanged::class, 'parameter_typing_added' => FunctionParameterTypingAdded::class, 'parameter_typing_removed' => FunctionParameterTypingRemoved::class, 'parameter_default_added' => FunctionParameterDefaultAdded::class, 'parameter_default_removed' => FunctionParameterDefaultRemoved::class, 'parameter_default_value_changed' => FunctionParameterDefaultValueChanged::class];
             foreach ($changes as $changeType => $class) {
                 if (!$signatureResult[$changeType]) {
                     continue;
                 }
                 if (is_a($class, FunctionOperationUnary::class, true)) {
                     $data = new $class($fileAfter, $functionAfter);
                 } else {
                     $data = new $class($fileBefore, $functionBefore, $fileAfter, $functionAfter);
                 }
                 $report->addFunction($data);
             }
             // Difference in source code
             if (!Implementation::isSame($functionBefore->stmts, $functionAfter->stmts)) {
                 $data = new FunctionImplementationChanged($fileBefore, $functionBefore, $fileAfter, $functionAfter);
                 $report->addFunction($data);
             }
         }
     }
     foreach ($added as $key) {
         $fileAfter = $registryAfter->mapping['function'][$key];
         $functionAfter = $registryAfter->data['function'][$key];
         $data = new FunctionAdded($fileAfter, $functionAfter);
         $report->addFunction($data);
     }
     return $report;
 }
 /**
  * @param \PHPSemVerChecker\Registry\Registry $registryBefore
  * @param \PHPSemVerChecker\Registry\Registry $registryAfter
  * @return \PHPSemVerChecker\Report\Report
  */
 public function analyze(Registry $registryBefore, Registry $registryAfter)
 {
     $report = new Report();
     $keysBefore = array_keys($registryBefore->data['function']);
     $keysAfter = array_keys($registryAfter->data['function']);
     $added = array_diff($keysAfter, $keysBefore);
     $removed = array_diff($keysBefore, $keysAfter);
     $toVerify = array_intersect($keysBefore, $keysAfter);
     foreach ($removed as $key) {
         $fileBefore = $registryBefore->mapping['function'][$key];
         $functionBefore = $registryBefore->data['function'][$key];
         $data = new FunctionRemoved($fileBefore, $functionBefore);
         $report->addFunction($data);
     }
     foreach ($toVerify as $key) {
         $fileBefore = $registryBefore->mapping['function'][$key];
         $functionBefore = $registryBefore->data['function'][$key];
         $fileAfter = $registryAfter->mapping['function'][$key];
         $functionAfter = $registryAfter->data['function'][$key];
         // Leave non-strict comparison here
         if ($functionBefore != $functionAfter) {
             $paramsBefore = $functionBefore->params;
             $paramsAfter = $functionAfter->params;
             // Signature
             if (!Signature::isSameTypehints($paramsBefore, $paramsAfter)) {
                 $data = new FunctionParameterChanged($fileBefore, $functionBefore, $fileAfter, $functionAfter);
                 $report->addFunction($data);
                 continue;
             }
             if (!Signature::isSameVariables($paramsBefore, $paramsAfter)) {
                 $data = new FunctionParameterNameChanged($fileBefore, $functionBefore, $fileAfter, $functionAfter);
                 $report->addFunction($data);
                 continue;
             }
             // Different length (considering params with defaults)
             // Difference in source code
             if ($functionBefore->stmts != $functionAfter->stmts) {
                 $data = new FunctionImplementationChanged($fileBefore, $functionBefore, $fileAfter, $functionAfter);
                 $report->addFunction($data);
                 continue;
             }
         }
     }
     foreach ($added as $key) {
         $fileAfter = $registryAfter->mapping['function'][$key];
         $functionAfter = $registryAfter->data['function'][$key];
         $data = new FunctionAdded($fileAfter, $functionAfter);
         $report->addFunction($data);
     }
     return $report;
 }