/**
  * Process the var tag.
  *
  * @param int $commentStart The position in the stack where the comment started.
  * @param int $commentEnd   The position in the stack where the comment ended.
  *
  * @return void
  */
 protected function processVar($commentStart, $commentEnd)
 {
     $var = $this->commentParser->getVar();
     if ($var !== null) {
         $errorPos = $commentStart + $var->getLine();
         $index = array_keys($this->commentParser->getTagOrders(), 'var');
         if (count($index) > 1) {
             $this->helper->addMessage($errorPos, M2_Sniffs_Annotations_Helper::DUPLICATE_VAR);
             return;
         }
         if ($index[0] !== 1) {
             $this->helper->addMessage($errorPos, M2_Sniffs_Annotations_Helper::VAR_ORDER);
         }
         $content = $var->getContent();
         if (empty($content) === true) {
             $this->helper->addMessage($errorPos, M2_Sniffs_Annotations_Helper::MISSING_VAR_TYPE);
             return;
         } else {
             $suggestedType = $this->helper->suggestType($content);
             if ($content !== $suggestedType) {
                 $data = [$suggestedType, $content];
                 $this->helper->addMessage($errorPos, M2_Sniffs_Annotations_Helper::INCORRECT_VAR_TYPE, $data);
             } elseif ($this->helper->isAmbiguous($content, $matches)) {
                 // Warn about ambiguous types ie array or mixed
                 $data = [$matches[1], '@var'];
                 $this->helper->addMessage($errorPos, M2_Sniffs_Annotations_Helper::AMBIGUOUS_TYPE, $data);
             }
         }
         $spacing = substr_count($var->getWhitespaceBeforeContent(), ' ');
         if ($spacing !== 1) {
             $data = [$spacing];
             $this->helper->addMessage($errorPos, M2_Sniffs_Annotations_Helper::VAR_INDENT, $data);
         }
     } else {
         $this->helper->addMessage($commentEnd, M2_Sniffs_Annotations_Helper::MISSING_VAR);
     }
 }
 /**
  * Processes each required or optional tag.
  *
  * @param int $commentStart Position in the stack where the comment started.
  * @param int $commentEnd   Position in the stack where the comment ended.
  *
  * @return void
  */
 protected function processTags($commentStart, $commentEnd)
 {
     $docBlock = get_class($this) === 'Windwalker_Sniffs_Commenting_FileCommentSniff' ? 'file' : 'class';
     $foundTags = $this->commentParser->getTagOrders();
     $orderIndex = 0;
     $indentation = array();
     $longestTag = 0;
     $errorPos = 0;
     foreach ($this->tags as $tag => $info) {
         // Required tag missing.
         if ($info['required'] === true && in_array($tag, $foundTags) === false) {
             $error = 'Missing @%s tag in %s comment';
             $data = array($tag, $docBlock);
             $this->currentFile->addError($error, $commentEnd, 'MissingTag', $data);
             continue;
         }
         // Get the line number for current tag.
         $tagName = ucfirst($tag);
         if ($info['allow_multiple'] === true) {
             $tagName .= 's';
         }
         $getMethod = 'get' . $tagName;
         $tagElement = $this->commentParser->{$getMethod}();
         if (is_null($tagElement) === true || empty($tagElement) === true) {
             continue;
         }
         $errorPos = $commentStart;
         if (is_array($tagElement) === false) {
             $errorPos = $commentStart + $tagElement->getLine();
         }
         // Get the tag order.
         $foundIndexes = array_keys($foundTags, $tag);
         if (count($foundIndexes) > 1) {
             // Multiple occurance not allowed.
             if ($info['allow_multiple'] === false) {
                 $error = 'Only 1 @%s tag is allowed in a %s comment';
                 $data = array($tag, $docBlock);
                 $this->currentFile->addError($error, $errorPos, 'DuplicateTag', $data);
             } else {
                 // Make sure same tags are grouped together.
                 $i = 0;
                 $count = $foundIndexes[0];
                 foreach ($foundIndexes as $index) {
                     if ($index !== $count) {
                         $errorPosIndex = $errorPos + $tagElement[$i]->getLine();
                         $error = '@%s tags must be grouped together';
                         $data = array($tag);
                         $this->currentFile->addError($error, $errorPosIndex, 'TagsNotGrouped', $data);
                     }
                     $i++;
                     $count++;
                 }
             }
         }
         //end if
         // Check tag order.
         if ($foundIndexes[0] > $orderIndex) {
             $orderIndex = $foundIndexes[0];
         } else {
             if (is_array($tagElement) === true && empty($tagElement) === false) {
                 $errorPos += $tagElement[0]->getLine();
             }
             $error = 'The @%s tag is in the wrong order; the tag %s';
             $data = array($tag, $info['order_text']);
             $this->currentFile->addError($error, $errorPos, 'WrongTagOrder', $data);
         }
         // Store the indentation for checking.
         $len = strlen($tag);
         if ($len > $longestTag) {
             $longestTag = $len;
         }
         if (is_array($tagElement) === true) {
             foreach ($tagElement as $key => $element) {
                 $indentation[] = array('tag' => $tag, 'space' => $this->getIndentation($tag, $element), 'line' => $element->getLine());
             }
         } else {
             $indentation[] = array('tag' => $tag, 'space' => $this->getIndentation($tag, $tagElement));
         }
         $method = 'process' . $tagName;
         if (method_exists($this, $method) === true) {
             // Process each tag if a method is defined.
             call_user_func(array($this, $method), $errorPos);
         } else {
             if (is_array($tagElement) === true) {
                 foreach ($tagElement as $key => $element) {
                     $element->process($this->currentFile, $commentStart, $docBlock);
                 }
             } else {
                 $tagElement->process($this->currentFile, $commentStart, $docBlock);
             }
         }
     }
     //end foreach
     foreach ($indentation as $indentInfo) {
         if ($indentInfo['space'] !== 0 && $indentInfo['space'] < $longestTag + 1) {
             $expected = $longestTag - strlen($indentInfo['tag']) + 1;
             $space = $indentInfo['space'] - strlen($indentInfo['tag']);
             $error = '@%s tag comment indented incorrectly; expected %s spaces but found %s';
             $data = array($indentInfo['tag'], $expected, $space);
             $getTagMethod = 'get' . ucfirst($indentInfo['tag']);
             if ($this->tags[$indentInfo['tag']]['allow_multiple'] === true) {
                 $line = $indentInfo['line'];
             } else {
                 $tagElem = $this->commentParser->{$getTagMethod}();
                 $line = $tagElem->getLine();
             }
             $this->currentFile->addError($error, $commentStart + $line, 'TagIndent', $data);
         }
     }
 }