Skip to content

Commit

Permalink
Refactor common logic into CommentMatcher (#28)
Browse files Browse the repository at this point in the history
Co-authored-by: staabm <staabm@users.noreply.github.com>
  • Loading branch information
staabm and staabm authored Dec 20, 2023
1 parent 9accc16 commit e88bd8b
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 54 deletions.
30 changes: 3 additions & 27 deletions src/TodoByDateRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\ShouldNotHappenException;
use staabm\PHPStanTodoBy\utils\CommentMatcher;
use staabm\PHPStanTodoBy\utils\ExpiredCommentErrorBuilder;
use function preg_match_all;
use function strtotime;
Expand Down Expand Up @@ -57,35 +58,10 @@ public function getNodeType(): string

public function processNode(Node $node, Scope $scope): array
{
if (
$node instanceof VirtualNode
|| $node instanceof Node\Expr
) {
// prevent duplicate errors
return [];
}
$it = CommentMatcher::matchComments($node, self::PATTERN);

$errors = [];

foreach ($node->getComments() as $comment) {

$text = $comment->getText();

/**
* PHP doc comments have the entire multi-line comment as the text.
* Since this could potentially contain multiple "todo" comments, we need to check all lines.
* This works for single line comments as well.
*
* PREG_OFFSET_CAPTURE: Track where each "todo" comment starts within the whole comment text.
* PREG_SET_ORDER: Make each value of $matches be structured the same as if from preg_match().
*/
if (
preg_match_all(self::PATTERN, $text, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER) === false
|| count($matches) === 0
) {
continue;
}

foreach($it as $comment => $matches) {
/** @var array<int, array<array{0: string, 1: int}>> $matches */
foreach ($matches as $match) {

Expand Down
30 changes: 3 additions & 27 deletions src/TodoByVersionRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use PHPStan\Node\VirtualNode;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use staabm\PHPStanTodoBy\utils\CommentMatcher;
use staabm\PHPStanTodoBy\utils\ExpiredCommentErrorBuilder;
use staabm\PHPStanTodoBy\utils\ReferenceVersionFinder;
use staabm\PHPStanTodoBy\utils\VersionNormalizer;
Expand Down Expand Up @@ -67,35 +68,10 @@ public function getNodeType(): string

public function processNode(Node $node, Scope $scope): array
{
if (
$node instanceof VirtualNode
|| $node instanceof Node\Expr
) {
// prevent duplicate errors
return [];
}
$it = CommentMatcher::matchComments($node, self::PATTERN);

$errors = [];

foreach ($node->getComments() as $comment) {

$text = $comment->getText();

/**
* PHP doc comments have the entire multi-line comment as the text.
* Since this could potentially contain multiple "todo" comments, we need to check all lines.
* This works for single line comments as well.
*
* PREG_OFFSET_CAPTURE: Track where each "todo" comment starts within the whole comment text.
* PREG_SET_ORDER: Make each value of $matches be structured the same as if from preg_match().
*/
if (
preg_match_all(self::PATTERN, $text, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER) === false
|| count($matches) === 0
) {
continue;
}

foreach($it as $comment => $matches) {
$referenceVersion = $this->getReferenceVersion($scope);

/** @var array<int, array<array{0: string, 1: int}>> $matches */
Expand Down
46 changes: 46 additions & 0 deletions src/utils/CommentMatcher.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace staabm\PHPStanTodoBy\utils;

use PhpParser\Comment;
use PHPStan\Node\VirtualNode;
use PhpParser\Node;

final class CommentMatcher
{
/**
* @return iterable<Comment, array<mixed>>
*/
public static function matchComments(Node $node, string $pattern): iterable
{
if (
$node instanceof VirtualNode
|| $node instanceof Node\Expr
) {
// prevent duplicate errors
return [];
}

foreach ($node->getComments() as $comment) {

$text = $comment->getText();

/**
* PHP doc comments have the entire multi-line comment as the text.
* Since this could potentially contain multiple "todo" comments, we need to check all lines.
* This works for single line comments as well.
*
* PREG_OFFSET_CAPTURE: Track where each "todo" comment starts within the whole comment text.
* PREG_SET_ORDER: Make each value of $matches be structured the same as if from preg_match().
*/
if (
preg_match_all($pattern, $text, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER) === false
|| count($matches) === 0
) {
continue;
}

yield $comment => $matches;
}
}
}

0 comments on commit e88bd8b

Please sign in to comment.