Completed
Push — master ( 9b18dc...e19264 )
by Tomáš
18s
created

ComponentFactoryCommentSniff   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 99
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 97.3%

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 1
dl 0
loc 99
ccs 36
cts 37
cp 0.973
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A register() 0 4 1
A process() 0 19 3
A isComponentFactoryMethod() 0 5 1
A getCommentEnd() 0 4 1
A hasMethodComment() 0 7 2
B processReturnTag() 0 20 6
1
<?php
2
3
declare(strict_types = 1);
4
5
/*
6
 * This file is part of Zenify
7
 * Copyright (c) 2012 Tomas Votruba (http://tomasvotruba.cz)
8
 */
9
10
namespace ZenifyCodingStandard\Sniffs\Commenting;
11
12
use PHP_CodeSniffer_File;
13
use PHP_CodeSniffer_Sniff;
14
15
16
/**
17
 * Rules:
18
 * - CreateComponent* method should have a doc comment.
19
 * - CreateComponent* method should have a return tag.
20
 * - Return tag should contain type.
21
 */
22
final class ComponentFactoryCommentSniff implements PHP_CodeSniffer_Sniff
23
{
24
25
	/**
26
	 * @var int
27
	 */
28
	private $position;
29
30
	/**
31
	 * @var PHP_CodeSniffer_File
32
	 */
33
	private $file;
34
35
	/**
36
	 * @var array
37
	 */
38
	private $tokens;
39
40
41
	/**
42
	 * {@inheritdoc}
43
	 */
44 1
	public function register()
45
	{
46 1
		return [T_FUNCTION];
47
	}
48
49
50
	/**
51
	 * {@inheritdoc}
52
	 */
53 1
	public function process(PHP_CodeSniffer_File $file, $position)
54
	{
55 1
		$this->file = $file;
56 1
		$this->position = $position;
57 1
		$this->tokens = $file->getTokens();
58
59 1
		if ( ! $this->isComponentFactoryMethod()) {
60
			return;
61
		}
62
63 1
		$commentEnd = $this->getCommentEnd();
64 1
		if ( ! $this->hasMethodComment($commentEnd)) {
0 ignored issues
show
Bug introduced by
It seems like $commentEnd defined by $this->getCommentEnd() on line 63 can also be of type boolean; however, ZenifyCodingStandard\Sni...iff::hasMethodComment() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
65 1
			$file->addError('CreateComponent* method should have a doc comment', $position);
66 1
			return;
67
		}
68
69 1
		$commentStart = $this->tokens[$commentEnd]['comment_opener'];
70 1
		$this->processReturnTag($commentStart);
71 1
	}
72
73
74 1
	private function isComponentFactoryMethod() : bool
75
	{
76 1
		$functionName = $this->file->getDeclarationName($this->position);
77 1
		return (strpos($functionName, 'createComponent') === 0);
78
	}
79
80
81
	/**
82
	 * @return bool|int
83
	 */
84 1
	private function getCommentEnd()
85
	{
86 1
		return $this->file->findPrevious(T_WHITESPACE, ($this->position - 3), NULL, TRUE);
87
	}
88
89
90 1
	private function hasMethodComment(int $position) : bool
91
	{
92 1
		if ($this->tokens[$position]['code'] === T_DOC_COMMENT_CLOSE_TAG) {
93 1
			return TRUE;
94
		}
95 1
		return FALSE;
96
	}
97
98
99 1
	private function processReturnTag(int $commentStartPosition)
100
	{
101 1
		$return = NULL;
102 1
		foreach ($this->tokens[$commentStartPosition]['comment_tags'] as $tag) {
103 1
			if ($this->tokens[$tag]['content'] === '@return') {
104 1
				$return = $tag;
105
			}
106
		}
107 1
		if ($return !== NULL) {
108 1
			$content = $this->tokens[($return + 2)]['content'];
109 1
			if (empty($content) === TRUE || $this->tokens[($return + 2)]['code'] !== T_DOC_COMMENT_STRING) {
110 1
				$error = 'Return tag should contain type';
111 1
				$this->file->addError($error, $return);
112
			}
113
114
		} else {
115 1
			$error = 'CreateComponent* method should have a @return tag';
116 1
			$this->file->addError($error, $this->tokens[$commentStartPosition]['comment_closer']);
117
		}
118 1
	}
119
120
}
121