Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. DocCommentSpacingSniff.php

class DocCommentSpacingSniff

Hierarchy

  • class \SlevomatCodingStandard\Sniffs\Commenting\DocCommentSpacingSniff implements \PHP_CodeSniffer\Sniffs\Sniff

Expanded class hierarchy of DocCommentSpacingSniff

File

vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DocCommentSpacingSniff.php, line 39

Namespace

SlevomatCodingStandard\Sniffs\Commenting
View source
class DocCommentSpacingSniff implements Sniff {
    public const CODE_INCORRECT_LINES_COUNT_BEFORE_FIRST_CONTENT = 'IncorrectLinesCountBeforeFirstContent';
    public const CODE_INCORRECT_LINES_COUNT_BETWEEN_DESCRIPTION_AND_ANNOTATIONS = 'IncorrectLinesCountBetweenDescriptionAndAnnotations';
    public const CODE_INCORRECT_LINES_COUNT_BETWEEN_DIFFERENT_ANNOTATIONS_TYPES = 'IncorrectLinesCountBetweenDifferentAnnotationsTypes';
    public const CODE_INCORRECT_LINES_COUNT_BETWEEN_ANNOTATIONS_GROUPS = 'IncorrectLinesCountBetweenAnnotationsGroups';
    public const CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTENT = 'IncorrectLinesCountAfterLastContent';
    public const CODE_INCORRECT_ANNOTATIONS_GROUP = 'IncorrectAnnotationsGroup';
    public const CODE_INCORRECT_ORDER_OF_ANNOTATIONS_GROUPS = 'IncorrectOrderOfAnnotationsGroup';
    public const CODE_INCORRECT_ORDER_OF_ANNOTATIONS_IN_GROUP = 'IncorrectOrderOfAnnotationsInGroup';
    
    /** @var int */
    public $linesCountBeforeFirstContent = 0;
    
    /** @var int */
    public $linesCountBetweenDescriptionAndAnnotations = 1;
    
    /** @var int */
    public $linesCountBetweenDifferentAnnotationsTypes = 0;
    
    /** @var int */
    public $linesCountBetweenAnnotationsGroups = 1;
    
    /** @var int */
    public $linesCountAfterLastContent = 0;
    
    /** @var list<string> */
    public $annotationsGroups = [];
    
    /** @var array<list<string>>|null */
    private $normalizedAnnotationsGroups = null;
    
    /**
     * @return array<int, (int|string)>
     */
    public function register() : array {
        return [
            T_DOC_COMMENT_OPEN_TAG,
        ];
    }
    
    /**
     * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
     * @param int $docCommentOpenerPointer
     */
    public function process(File $phpcsFile, $docCommentOpenerPointer) : void {
        $this->linesCountBeforeFirstContent = SniffSettingsHelper::normalizeInteger($this->linesCountBeforeFirstContent);
        $this->linesCountBetweenDescriptionAndAnnotations = SniffSettingsHelper::normalizeInteger($this->linesCountBetweenDescriptionAndAnnotations);
        $this->linesCountBetweenDifferentAnnotationsTypes = SniffSettingsHelper::normalizeInteger($this->linesCountBetweenDifferentAnnotationsTypes);
        $this->linesCountBetweenAnnotationsGroups = SniffSettingsHelper::normalizeInteger($this->linesCountBetweenAnnotationsGroups);
        $this->linesCountAfterLastContent = SniffSettingsHelper::normalizeInteger($this->linesCountAfterLastContent);
        if (DocCommentHelper::isInline($phpcsFile, $docCommentOpenerPointer)) {
            return;
        }
        $tokens = $phpcsFile->getTokens();
        if (TokenHelper::findNextExcluding($phpcsFile, [
            T_DOC_COMMENT_WHITESPACE,
            T_DOC_COMMENT_STAR,
        ], $docCommentOpenerPointer + 1, $tokens[$docCommentOpenerPointer]['comment_closer']) === null) {
            return;
        }
        $parsedDocComment = DocCommentHelper::parseDocComment($phpcsFile, $docCommentOpenerPointer);
        if ($parsedDocComment === null) {
            return;
        }
        $firstContentStartPointer = $parsedDocComment->getNodeStartPointer($phpcsFile, $parsedDocComment->getNode()->children[0]);
        $firstContentEndPointer = $parsedDocComment->getNodeEndPointer($phpcsFile, $parsedDocComment->getNode()->children[0], $firstContentStartPointer);
        $annotations = AnnotationHelper::getAnnotations($phpcsFile, $docCommentOpenerPointer);
        usort($annotations, static function (Annotation $a, Annotation $b) : int {
            return $a->getStartPointer() <=> $b->getStartPointer();
        });
        $annotationsCount = count($annotations);
        $firstAnnotationPointer = $annotationsCount > 0 ? $annotations[0]->getStartPointer() : null;
        
        /** @var int $lastContentEndPointer */
        $lastContentEndPointer = $annotationsCount > 0 ? $annotations[$annotationsCount - 1]->getEndPointer() : $firstContentEndPointer;
        $this->checkLinesBeforeFirstContent($phpcsFile, $docCommentOpenerPointer, $firstContentStartPointer);
        $this->checkLinesBetweenDescriptionAndFirstAnnotation($phpcsFile, $docCommentOpenerPointer, $firstContentStartPointer, $firstContentEndPointer, $firstAnnotationPointer);
        if (count($annotations) > 1) {
            if (count($this->getAnnotationsGroups()) === 0) {
                $this->checkLinesBetweenDifferentAnnotationsTypes($phpcsFile, $docCommentOpenerPointer, $annotations);
            }
            else {
                $this->checkAnnotationsGroups($phpcsFile, $docCommentOpenerPointer, $annotations);
            }
        }
        $this->checkLinesAfterLastContent($phpcsFile, $docCommentOpenerPointer, $tokens[$docCommentOpenerPointer]['comment_closer'], $lastContentEndPointer);
    }
    private function checkLinesBeforeFirstContent(File $phpcsFile, int $docCommentOpenerPointer, int $firstContentStartPointer) : void {
        $tokens = $phpcsFile->getTokens();
        $whitespaceBeforeFirstContent = substr($tokens[$docCommentOpenerPointer]['content'], 0, strlen('/**'));
        $whitespaceBeforeFirstContent .= TokenHelper::getContent($phpcsFile, $docCommentOpenerPointer + 1, $firstContentStartPointer - 1);
        $linesCountBeforeFirstContent = max(substr_count($whitespaceBeforeFirstContent, $phpcsFile->eolChar) - 1, 0);
        if ($linesCountBeforeFirstContent === $this->linesCountBeforeFirstContent) {
            return;
        }
        $fix = $phpcsFile->addFixableError(sprintf('Expected %d line%s before first content, found %d.', $this->linesCountBeforeFirstContent, $this->linesCountBeforeFirstContent === 1 ? '' : 's', $linesCountBeforeFirstContent), $firstContentStartPointer, self::CODE_INCORRECT_LINES_COUNT_BEFORE_FIRST_CONTENT);
        if (!$fix) {
            return;
        }
        $indentation = IndentationHelper::getIndentation($phpcsFile, $docCommentOpenerPointer);
        $phpcsFile->fixer
            ->beginChangeset();
        FixerHelper::change($phpcsFile, $docCommentOpenerPointer, $firstContentStartPointer - 1, '/**' . $phpcsFile->eolChar);
        for ($i = 1; $i <= $this->linesCountBeforeFirstContent; $i++) {
            $phpcsFile->fixer
                ->addContent($docCommentOpenerPointer, sprintf('%s *%s', $indentation, $phpcsFile->eolChar));
        }
        $phpcsFile->fixer
            ->addContentBefore($firstContentStartPointer, $indentation . ' * ');
        $phpcsFile->fixer
            ->endChangeset();
    }
    private function checkLinesBetweenDescriptionAndFirstAnnotation(File $phpcsFile, int $docCommentOpenerPointer, int $firstContentStartPointer, int $firstContentEndPointer, ?int $firstAnnotationPointer) : void {
        if ($firstAnnotationPointer === null) {
            return;
        }
        if ($firstContentStartPointer === $firstAnnotationPointer) {
            return;
        }
        $tokens = $phpcsFile->getTokens();
        preg_match('~(\\s+)$~', $tokens[$firstContentEndPointer]['content'], $matches);
        $whitespaceBetweenDescriptionAndFirstAnnotation = $matches[1] ?? '';
        $whitespaceBetweenDescriptionAndFirstAnnotation .= TokenHelper::getContent($phpcsFile, $firstContentEndPointer + 1, $firstAnnotationPointer - 1);
        $linesCountBetweenDescriptionAndAnnotations = max(substr_count($whitespaceBetweenDescriptionAndFirstAnnotation, $phpcsFile->eolChar) - 1, 0);
        if ($linesCountBetweenDescriptionAndAnnotations === $this->linesCountBetweenDescriptionAndAnnotations) {
            return;
        }
        $fix = $phpcsFile->addFixableError(sprintf('Expected %d line%s between description and annotations, found %d.', $this->linesCountBetweenDescriptionAndAnnotations, $this->linesCountBetweenDescriptionAndAnnotations === 1 ? '' : 's', $linesCountBetweenDescriptionAndAnnotations), $firstAnnotationPointer, self::CODE_INCORRECT_LINES_COUNT_BETWEEN_DESCRIPTION_AND_ANNOTATIONS);
        if (!$fix) {
            return;
        }
        $indentation = IndentationHelper::getIndentation($phpcsFile, $docCommentOpenerPointer);
        $phpcsFile->fixer
            ->beginChangeset();
        $phpcsFile->fixer
            ->addNewline($firstContentEndPointer);
        FixerHelper::removeBetween($phpcsFile, $firstContentEndPointer, $firstAnnotationPointer);
        for ($i = 1; $i <= $this->linesCountBetweenDescriptionAndAnnotations; $i++) {
            $phpcsFile->fixer
                ->addContent($firstContentEndPointer, sprintf('%s *%s', $indentation, $phpcsFile->eolChar));
        }
        $phpcsFile->fixer
            ->addContentBefore($firstAnnotationPointer, $indentation . ' * ');
        $phpcsFile->fixer
            ->endChangeset();
    }
    
    /**
     * @param list<Annotation> $annotations
     */
    private function checkLinesBetweenDifferentAnnotationsTypes(File $phpcsFile, int $docCommentOpenerPointer, array $annotations) : void {
        $indentation = IndentationHelper::getIndentation($phpcsFile, $docCommentOpenerPointer);
        $previousAnnotation = null;
        foreach ($annotations as $annotation) {
            if ($previousAnnotation === null) {
                $previousAnnotation = $annotation;
                continue;
            }
            if ($annotation->getName() === $previousAnnotation->getName()) {
                $previousAnnotation = $annotation;
                continue;
            }
            $whitespaceAfterPreviousAnnotation = TokenHelper::getContent($phpcsFile, $previousAnnotation->getEndPointer() + 1, $annotation->getStartPointer() - 1);
            $linesCountAfterPreviousAnnotation = max(substr_count($whitespaceAfterPreviousAnnotation, $phpcsFile->eolChar) - 1, 0);
            if ($linesCountAfterPreviousAnnotation === $this->linesCountBetweenDifferentAnnotationsTypes) {
                $previousAnnotation = $annotation;
                continue;
            }
            $fix = $phpcsFile->addFixableError(sprintf('Expected %d line%s between different annotations types, found %d.', $this->linesCountBetweenDifferentAnnotationsTypes, $this->linesCountBetweenDifferentAnnotationsTypes === 1 ? '' : 's', $linesCountAfterPreviousAnnotation), $annotation->getStartPointer(), self::CODE_INCORRECT_LINES_COUNT_BETWEEN_DIFFERENT_ANNOTATIONS_TYPES);
            if (!$fix) {
                $previousAnnotation = $annotation;
                continue;
            }
            $phpcsFile->fixer
                ->beginChangeset();
            FixerHelper::removeBetween($phpcsFile, $previousAnnotation->getEndPointer(), $annotation->getStartPointer());
            $phpcsFile->fixer
                ->addNewline($previousAnnotation->getEndPointer());
            for ($i = 1; $i <= $this->linesCountBetweenDifferentAnnotationsTypes; $i++) {
                $phpcsFile->fixer
                    ->addContent($previousAnnotation->getEndPointer(), sprintf('%s *%s', $indentation, $phpcsFile->eolChar));
            }
            $phpcsFile->fixer
                ->addContentBefore($annotation->getStartPointer(), $indentation . ' * ');
            $phpcsFile->fixer
                ->endChangeset();
            $previousAnnotation = $annotation;
        }
    }
    
    /**
     * @param list<Annotation> $annotations
     */
    private function checkAnnotationsGroups(File $phpcsFile, int $docCommentOpenerPointer, array $annotations) : void {
        $tokens = $phpcsFile->getTokens();
        $annotationsGroups = [];
        $annotationsGroup = [];
        $previousAnnotation = null;
        foreach ($annotations as $annotation) {
            if ($previousAnnotation === null || $tokens[$previousAnnotation->getEndPointer()]['line'] + 1 === $tokens[$annotation->getStartPointer()]['line']) {
                $annotationsGroup[] = $annotation;
                $previousAnnotation = $annotation;
                continue;
            }
            $annotationsGroups[] = $annotationsGroup;
            $annotationsGroup = [
                $annotation,
            ];
            $previousAnnotation = $annotation;
        }
        if (count($annotationsGroup) > 0) {
            $annotationsGroups[] = $annotationsGroup;
        }
        $this->checkAnnotationsGroupsOrder($phpcsFile, $docCommentOpenerPointer, $annotationsGroups, $annotations);
        $this->checkLinesBetweenAnnotationsGroups($phpcsFile, $docCommentOpenerPointer, $annotationsGroups);
    }
    
    /**
     * @param list<list<Annotation>> $annotationsGroups
     */
    private function checkLinesBetweenAnnotationsGroups(File $phpcsFile, int $docCommentOpenerPointer, array $annotationsGroups) : void {
        $tokens = $phpcsFile->getTokens();
        $previousAnnotationsGroup = null;
        foreach ($annotationsGroups as $annotationsGroup) {
            if ($previousAnnotationsGroup === null) {
                $previousAnnotationsGroup = $annotationsGroup;
                continue;
            }
            $lastAnnotationInPreviousGroup = $previousAnnotationsGroup[count($previousAnnotationsGroup) - 1];
            $firstAnnotationInActualGroup = $annotationsGroup[0];
            $actualLinesCountBetweenAnnotationsGroups = $tokens[$firstAnnotationInActualGroup->getStartPointer()]['line'] - $tokens[$lastAnnotationInPreviousGroup->getEndPointer()]['line'] - 1;
            if ($actualLinesCountBetweenAnnotationsGroups === $this->linesCountBetweenAnnotationsGroups) {
                $previousAnnotationsGroup = $annotationsGroup;
                continue;
            }
            $fix = $phpcsFile->addFixableError(sprintf('Expected %d line%s between annotations groups, found %d.', $this->linesCountBetweenAnnotationsGroups, $this->linesCountBetweenAnnotationsGroups === 1 ? '' : 's', $actualLinesCountBetweenAnnotationsGroups), $firstAnnotationInActualGroup->getStartPointer(), self::CODE_INCORRECT_LINES_COUNT_BETWEEN_ANNOTATIONS_GROUPS);
            if (!$fix) {
                $previousAnnotationsGroup = $annotationsGroup;
                continue;
            }
            $indentation = IndentationHelper::getIndentation($phpcsFile, $docCommentOpenerPointer);
            $phpcsFile->fixer
                ->beginChangeset();
            $phpcsFile->fixer
                ->addNewline($lastAnnotationInPreviousGroup->getEndPointer());
            FixerHelper::removeBetween($phpcsFile, $lastAnnotationInPreviousGroup->getEndPointer(), $firstAnnotationInActualGroup->getStartPointer());
            for ($i = 1; $i <= $this->linesCountBetweenAnnotationsGroups; $i++) {
                $phpcsFile->fixer
                    ->addContent($lastAnnotationInPreviousGroup->getEndPointer(), sprintf('%s *%s', $indentation, $phpcsFile->eolChar));
            }
            $phpcsFile->fixer
                ->addContentBefore($firstAnnotationInActualGroup->getStartPointer(), $indentation . ' * ');
            $phpcsFile->fixer
                ->endChangeset();
        }
    }
    
    /**
     * @param list<list<Annotation>> $annotationsGroups
     * @param list<Annotation> $annotations
     */
    private function checkAnnotationsGroupsOrder(File $phpcsFile, int $docCommentOpenerPointer, array $annotationsGroups, array $annotations) : void {
        $getAnnotationsPointers = static function (Annotation $annotation) : int {
            return $annotation->getStartPointer();
        };
        $equals = static function (array $firstAnnotationsGroup, array $secondAnnotationsGroup) use ($getAnnotationsPointers) : bool {
            $firstAnnotationsPointers = array_map($getAnnotationsPointers, $firstAnnotationsGroup);
            $secondAnnotationsPointers = array_map($getAnnotationsPointers, $secondAnnotationsGroup);
            return count(array_diff($firstAnnotationsPointers, $secondAnnotationsPointers)) === 0 && count(array_diff($secondAnnotationsPointers, $firstAnnotationsPointers)) === 0;
        };
        $sortedAnnotationsGroups = $this->sortAnnotationsToGroups($annotations);
        $incorrectAnnotationsGroupsExist = false;
        $annotationsGroupsPositions = [];
        $fix = false;
        $undefinedAnnotationsGroups = [];
        foreach ($annotationsGroups as $annotationsGroupPosition => $annotationsGroup) {
            foreach ($sortedAnnotationsGroups as $sortedAnnotationsGroupPosition => $sortedAnnotationsGroup) {
                if ($equals($annotationsGroup, $sortedAnnotationsGroup)) {
                    $annotationsGroupsPositions[$annotationsGroupPosition] = $sortedAnnotationsGroupPosition;
                    continue 2;
                }
                $undefinedAnnotationsGroup = true;
                foreach ($annotationsGroup as $annotation) {
                    foreach ($this->getAnnotationsGroups() as $annotationNames) {
                        foreach ($annotationNames as $annotationName) {
                            if ($this->isAnnotationMatched($annotation, $annotationName)) {
                                $undefinedAnnotationsGroup = false;
                                break 3;
                            }
                        }
                    }
                }
                if ($undefinedAnnotationsGroup) {
                    $undefinedAnnotationsGroups[] = $annotationsGroupPosition;
                    continue 2;
                }
            }
            $incorrectAnnotationsGroupsExist = true;
            $fix = $phpcsFile->addFixableError('Incorrect annotations group.', $annotationsGroup[0]->getStartPointer(), self::CODE_INCORRECT_ANNOTATIONS_GROUP);
        }
        if (count($annotationsGroupsPositions) === 0 && count($undefinedAnnotationsGroups) > 1) {
            $incorrectAnnotationsGroupsExist = true;
            $fix = $phpcsFile->addFixableError('Incorrect annotations group.', $annotationsGroups[0][0]->getStartPointer(), self::CODE_INCORRECT_ANNOTATIONS_GROUP);
        }
        if (!$incorrectAnnotationsGroupsExist) {
            foreach ($undefinedAnnotationsGroups as $undefinedAnnotationsGroupPosition) {
                $annotationsGroupsPositions[$undefinedAnnotationsGroupPosition] = (count($annotationsGroupsPositions) > 0 ? max($annotationsGroupsPositions) : 0) + 1;
            }
            ksort($annotationsGroupsPositions);
            $positionsMappedToGroups = array_keys($annotationsGroupsPositions);
            $tmp = array_values($annotationsGroupsPositions);
            asort($tmp);
            
            /** @var list<int> $normalizedAnnotationsGroupsPositions */
            $normalizedAnnotationsGroupsPositions = array_combine(array_keys($positionsMappedToGroups), array_keys($tmp));
            foreach ($normalizedAnnotationsGroupsPositions as $normalizedAnnotationsGroupPosition => $sortedAnnotationsGroupPosition) {
                if ($normalizedAnnotationsGroupPosition === $sortedAnnotationsGroupPosition) {
                    continue;
                }
                $fix = $phpcsFile->addFixableError('Incorrect order of annotations groups.', $annotationsGroups[$positionsMappedToGroups[$normalizedAnnotationsGroupPosition]][0]->getStartPointer(), self::CODE_INCORRECT_ORDER_OF_ANNOTATIONS_GROUPS);
                break;
            }
        }
        foreach ($annotationsGroups as $annotationsGroupPosition => $annotationsGroup) {
            if (!array_key_exists($annotationsGroupPosition, $annotationsGroupsPositions)) {
                continue;
            }
            if (!array_key_exists($annotationsGroupsPositions[$annotationsGroupPosition], $sortedAnnotationsGroups)) {
                continue;
            }
            $sortedAnnotationsGroup = $sortedAnnotationsGroups[$annotationsGroupsPositions[$annotationsGroupPosition]];
            foreach ($annotationsGroup as $annotationPosition => $annotation) {
                if ($annotation === $sortedAnnotationsGroup[$annotationPosition]) {
                    continue;
                }
                $fix = $phpcsFile->addFixableError('Incorrect order of annotations in group.', $annotation->getStartPointer(), self::CODE_INCORRECT_ORDER_OF_ANNOTATIONS_IN_GROUP);
                break;
            }
        }
        if (!$fix) {
            return;
        }
        $firstAnnotation = $annotationsGroups[0][0];
        $lastAnnotationsGroup = $annotationsGroups[count($annotationsGroups) - 1];
        $lastAnnotation = $lastAnnotationsGroup[count($lastAnnotationsGroup) - 1];
        $indentation = IndentationHelper::getIndentation($phpcsFile, $docCommentOpenerPointer);
        $fixedAnnotations = '';
        $firstGroup = true;
        foreach ($sortedAnnotationsGroups as $sortedAnnotationsGroup) {
            if ($firstGroup) {
                $firstGroup = false;
            }
            else {
                for ($i = 0; $i < $this->linesCountBetweenAnnotationsGroups; $i++) {
                    $fixedAnnotations .= sprintf('%s *%s', $indentation, $phpcsFile->eolChar);
                }
            }
            foreach ($sortedAnnotationsGroup as $sortedAnnotation) {
                $fixedAnnotations .= sprintf('%s * %s%s', $indentation, trim(TokenHelper::getContent($phpcsFile, $sortedAnnotation->getStartPointer(), $sortedAnnotation->getEndPointer())), $phpcsFile->eolChar);
            }
        }
        $tokens = $phpcsFile->getTokens();
        $docCommentCloserPointer = $tokens[$docCommentOpenerPointer]['comment_closer'];
        $endOfLineBeforeFirstAnnotation = TokenHelper::findPreviousContent($phpcsFile, T_DOC_COMMENT_WHITESPACE, $phpcsFile->eolChar, $firstAnnotation->getStartPointer() - 1, $docCommentOpenerPointer);
        $docCommentContentEndPointer = TokenHelper::findNextContent($phpcsFile, T_DOC_COMMENT_WHITESPACE, $phpcsFile->eolChar, $lastAnnotation->getEndPointer() + 1, $docCommentCloserPointer);
        if ($docCommentContentEndPointer === null) {
            $docCommentContentEndPointer = $lastAnnotation->getEndPointer();
        }
        $phpcsFile->fixer
            ->beginChangeset();
        if ($endOfLineBeforeFirstAnnotation === null) {
            FixerHelper::change($phpcsFile, $docCommentOpenerPointer, $docCommentContentEndPointer, '/**' . $phpcsFile->eolChar . $fixedAnnotations);
        }
        else {
            FixerHelper::change($phpcsFile, $endOfLineBeforeFirstAnnotation + 1, $docCommentContentEndPointer, $fixedAnnotations);
        }
        $phpcsFile->fixer
            ->endChangeset();
    }
    
    /**
     * @param list<Annotation> $annotations
     * @return list<list<Annotation>>
     */
    private function sortAnnotationsToGroups(array $annotations) : array {
        $expectedAnnotationsGroups = $this->getAnnotationsGroups();
        $sortedAnnotationsGroups = [];
        $annotationsNotInAnyGroup = [];
        foreach ($annotations as $annotation) {
            foreach ($expectedAnnotationsGroups as $annotationsGroupPosition => $annotationsGroup) {
                foreach ($annotationsGroup as $annotationName) {
                    if ($this->isAnnotationMatched($annotation, $annotationName)) {
                        $sortedAnnotationsGroups[$annotationsGroupPosition][] = $annotation;
                        continue 3;
                    }
                }
            }
            $annotationsNotInAnyGroup[] = $annotation;
        }
        ksort($sortedAnnotationsGroups);
        foreach (array_keys($sortedAnnotationsGroups) as $annotationsGroupPosition) {
            $expectedAnnotationsGroupOrder = array_flip($expectedAnnotationsGroups[$annotationsGroupPosition]);
            usort($sortedAnnotationsGroups[$annotationsGroupPosition], function (Annotation $firstAnnotation, Annotation $secondAnnotation) use ($expectedAnnotationsGroupOrder) : int {
                $getExpectedOrder = function (string $annotationName) use ($expectedAnnotationsGroupOrder) : int {
                    if (array_key_exists($annotationName, $expectedAnnotationsGroupOrder)) {
                        return $expectedAnnotationsGroupOrder[$annotationName];
                    }
                    $order = 0;
                    foreach ($expectedAnnotationsGroupOrder as $expectedAnnotationName => $expectedAnnotationOrder) {
                        if ($this->isAnnotationNameInAnnotationNamespace($expectedAnnotationName, $annotationName)) {
                            $order = $expectedAnnotationOrder;
                            break;
                        }
                    }
                    return $order;
                };
                $expectedOrder = $getExpectedOrder($firstAnnotation->getName()) <=> $getExpectedOrder($secondAnnotation->getName());
                return $expectedOrder !== 0 ? $expectedOrder : $firstAnnotation->getStartPointer() <=> $secondAnnotation->getStartPointer();
            });
        }
        if (count($annotationsNotInAnyGroup) > 0) {
            $sortedAnnotationsGroups[] = $annotationsNotInAnyGroup;
        }
        return $sortedAnnotationsGroups;
    }
    private function isAnnotationNameInAnnotationNamespace(string $annotationNamespace, string $annotationName) : bool {
        return $this->isAnnotationStartedFrom($annotationNamespace, $annotationName) || in_array(substr($annotationNamespace, -1), [
            '\\',
            '-',
            ':',
        ], true) && strpos($annotationName, $annotationNamespace) === 0;
    }
    private function isAnnotationStartedFrom(string $annotationNamespace, string $annotationName) : bool {
        return substr($annotationNamespace, -1) === '*' && strpos($annotationName, substr($annotationNamespace, 0, -1)) === 0;
    }
    private function isAnnotationMatched(Annotation $annotation, string $annotationName) : bool {
        if ($annotation->getName() === $annotationName) {
            return true;
        }
        return $this->isAnnotationNameInAnnotationNamespace($annotationName, $annotation->getName());
    }
    private function checkLinesAfterLastContent(File $phpcsFile, int $docCommentOpenerPointer, int $docCommentCloserPointer, int $lastContentEndPointer) : void {
        $whitespaceAfterLastContent = TokenHelper::getContent($phpcsFile, $lastContentEndPointer + 1, $docCommentCloserPointer);
        $linesCountAfterLastContent = max(substr_count($whitespaceAfterLastContent, $phpcsFile->eolChar) - 1, 0);
        if ($linesCountAfterLastContent === $this->linesCountAfterLastContent) {
            return;
        }
        $fix = $phpcsFile->addFixableError(sprintf('Expected %d line%s after last content, found %d.', $this->linesCountAfterLastContent, $this->linesCountAfterLastContent === 1 ? '' : 's', $linesCountAfterLastContent), $lastContentEndPointer, self::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTENT);
        if (!$fix) {
            return;
        }
        $indentation = IndentationHelper::getIndentation($phpcsFile, $docCommentOpenerPointer);
        $phpcsFile->fixer
            ->beginChangeset();
        FixerHelper::removeBetween($phpcsFile, $lastContentEndPointer, $docCommentCloserPointer);
        $phpcsFile->fixer
            ->addNewline($lastContentEndPointer);
        for ($i = 1; $i <= $this->linesCountAfterLastContent; $i++) {
            $phpcsFile->fixer
                ->addContent($lastContentEndPointer, sprintf('%s *%s', $indentation, $phpcsFile->eolChar));
        }
        $phpcsFile->fixer
            ->addContentBefore($docCommentCloserPointer, $indentation . ' ');
        $phpcsFile->fixer
            ->endChangeset();
    }
    
    /**
     * @return array<list<string>>
     */
    private function getAnnotationsGroups() : array {
        if ($this->normalizedAnnotationsGroups === null) {
            $this->normalizedAnnotationsGroups = [];
            foreach ($this->annotationsGroups as $annotationsGroup) {
                $this->normalizedAnnotationsGroups[] = SniffSettingsHelper::normalizeArray(explode(',', $annotationsGroup));
            }
        }
        return $this->normalizedAnnotationsGroups;
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title
DocCommentSpacingSniff::$annotationsGroups public property @var list&lt;string&gt;
DocCommentSpacingSniff::$linesCountAfterLastContent public property @var int
DocCommentSpacingSniff::$linesCountBeforeFirstContent public property @var int
DocCommentSpacingSniff::$linesCountBetweenAnnotationsGroups public property @var int
DocCommentSpacingSniff::$linesCountBetweenDescriptionAndAnnotations public property @var int
DocCommentSpacingSniff::$linesCountBetweenDifferentAnnotationsTypes public property @var int
DocCommentSpacingSniff::$normalizedAnnotationsGroups private property @var array&lt;list&lt;string&gt;&gt;|null
DocCommentSpacingSniff::checkAnnotationsGroups private function *
DocCommentSpacingSniff::checkAnnotationsGroupsOrder private function *
DocCommentSpacingSniff::checkLinesAfterLastContent private function
DocCommentSpacingSniff::checkLinesBeforeFirstContent private function
DocCommentSpacingSniff::checkLinesBetweenAnnotationsGroups private function *
DocCommentSpacingSniff::checkLinesBetweenDescriptionAndFirstAnnotation private function
DocCommentSpacingSniff::checkLinesBetweenDifferentAnnotationsTypes private function *
DocCommentSpacingSniff::CODE_INCORRECT_ANNOTATIONS_GROUP public constant
DocCommentSpacingSniff::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTENT public constant
DocCommentSpacingSniff::CODE_INCORRECT_LINES_COUNT_BEFORE_FIRST_CONTENT public constant
DocCommentSpacingSniff::CODE_INCORRECT_LINES_COUNT_BETWEEN_ANNOTATIONS_GROUPS public constant
DocCommentSpacingSniff::CODE_INCORRECT_LINES_COUNT_BETWEEN_DESCRIPTION_AND_ANNOTATIONS public constant
DocCommentSpacingSniff::CODE_INCORRECT_LINES_COUNT_BETWEEN_DIFFERENT_ANNOTATIONS_TYPES public constant
DocCommentSpacingSniff::CODE_INCORRECT_ORDER_OF_ANNOTATIONS_GROUPS public constant
DocCommentSpacingSniff::CODE_INCORRECT_ORDER_OF_ANNOTATIONS_IN_GROUP public constant
DocCommentSpacingSniff::getAnnotationsGroups private function *
DocCommentSpacingSniff::isAnnotationMatched private function
DocCommentSpacingSniff::isAnnotationNameInAnnotationNamespace private function
DocCommentSpacingSniff::isAnnotationStartedFrom private function
DocCommentSpacingSniff::process public function * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
*
Overrides Sniff::process
DocCommentSpacingSniff::register public function * Overrides Sniff::register
DocCommentSpacingSniff::sortAnnotationsToGroups private function *
RSS feed
Powered by Drupal