Completed
Push — master ( 1a6e67...071a29 )
by Tomáš
02:38
created

PropertiesMethodsMutualSpacingSniff   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 133
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 89.58%

Importance

Changes 0
Metric Value
wmc 15
lcom 1
cbo 3
dl 0
loc 133
ccs 43
cts 48
cp 0.8958
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A register() 0 4 1
B process() 0 33 5
A isLastProperty() 0 9 2
A isInsideMethod() 0 5 1
A areMethodsPresent() 0 5 1
A getPositionOfLastProperty() 0 16 4
A fixSpacingInBetween() 0 11 1
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\WhiteSpace;
11
12
use PHP_CodeSniffer_File;
13
use PHP_CodeSniffer_Sniff;
14
use ZenifyCodingStandard\Helper\PositionFinder;
15
use ZenifyCodingStandard\Helper\Whitespace\EmptyLinesResizer;
16
17
18
/**
19
 * Rules:
20
 * - Between properties and methods should be x empty line(s).
21
 */
22
final class PropertiesMethodsMutualSpacingSniff implements PHP_CodeSniffer_Sniff
23
{
24
25
	/**
26
	 * @var string
27
	 */
28
	const NAME = 'ZenifyCodingStandard.WhiteSpace.PropertiesMethodsMutualSpacing';
29
30
	/**
31
	 * @var int
32
	 */
33
	public $desiredBlankLinesInBetween = 2;
34
35
	/**
36
	 * @var PHP_CodeSniffer_File
37
	 */
38
	private $file;
39
40
	/**
41
	 * @var int
42
	 */
43
	private $position;
44
45
	/**
46
	 * @var array
47
	 */
48
	private $tokens;
49
50
51
	/**
52
	 * @return int[]
53
	 */
54 2
	public function register() : array
55
	{
56 2
		return [T_VARIABLE];
57
	}
58
59
60
	/**
61
	 * @param PHP_CodeSniffer_File $file
62
	 * @param int $position
63
	 */
64 2
	public function process(PHP_CodeSniffer_File $file, $position)
65
	{
66 2
		$this->file = $file;
67 2
		$this->position = $position;
68 2
		$this->tokens = $file->getTokens();
69
70
		// Fix type
71 2
		$this->desiredBlankLinesInBetween = (int) $this->desiredBlankLinesInBetween;
72
73 2
		if ($this->isLastProperty() === FALSE) {
74
			return;
75
		}
76
77 2
		if ($this->areMethodsPresent() === FALSE) {
78
			return;
79
		}
80
81 2
		$next = $file->findNext([T_DOC_COMMENT_OPEN_TAG, T_FUNCTION], $position);
82
83 2
		$positionOfLastProperty = $this->getPositionOfLastProperty();
84 2
		$blankLines = $this->tokens[$next]['line'] - $this->tokens[$positionOfLastProperty]['line'] - 1;
85 2
		if ($blankLines !== $this->desiredBlankLinesInBetween) {
86 2
			$error = sprintf(
87 2
				'Between properties and methods should be %s empty line(s); %s found.',
88 2
				$this->desiredBlankLinesInBetween,
89
				$blankLines
90
			);
91 2
			$fix = $file->addFixableError($error, $position);
92 2
			if ($fix) {
93 1
				$this->fixSpacingInBetween($blankLines);
94
			}
95
		}
96 2
	}
97
98
99 2
	private function isLastProperty() : bool
100
	{
101 2
		if ($this->isInsideMethod()) {
102
			return FALSE;
103
		}
104
105 2
		$next = $this->file->findNext([T_VARIABLE, T_FUNCTION], $this->position + 1);
106 2
		return $this->tokens[$next]['code'] !== T_VARIABLE;
107
	}
108
109
110 2
	private function isInsideMethod() : bool
111
	{
112 2
		$previousMethod = $this->file->findPrevious(T_FUNCTION, $this->position);
113 2
		return $this->tokens[$previousMethod]['code'] === T_FUNCTION;
114
	}
115
116
117 2
	private function areMethodsPresent() : bool
118
	{
119 2
		$next = $this->file->findNext(T_FUNCTION, $this->position + 1);
120 2
		return $this->tokens[$next]['code'] === T_FUNCTION;
121
	}
122
123
124 2
	private function getPositionOfLastProperty() : int
125
	{
126 2
		$arrayPosition = $this->file->findNext(T_ARRAY, $this->position);
127 2
		if ($this->tokens[$arrayPosition]['line'] === $this->tokens[$this->position]['line']) {
128
			if ($this->tokens[$arrayPosition]['parenthesis_closer']) {
129
				return $this->tokens[$arrayPosition]['parenthesis_closer'];
130
			}
131
		}
132
133 2
		$openShortArrayPosition = $this->file->findNext(T_OPEN_SHORT_ARRAY, $this->position);
134 2
		if ($this->tokens[$openShortArrayPosition]['line'] === $this->tokens[$this->position]['line']) {
135 1
			return $this->tokens[$openShortArrayPosition]['bracket_closer'];
136
		}
137
138 2
		return $this->position;
139
	}
140
141
142 1
	private function fixSpacingInBetween(int $blankLinesInBetween)
143
	{
144 1
		$position = PositionFinder::findLastPositionInCurrentLine($this->file, $this->getPositionOfLastProperty());
145
146 1
		EmptyLinesResizer::resizeLines(
147 1
			$this->file,
148
			$position,
149
			$blankLinesInBetween,
150 1
			$this->desiredBlankLinesInBetween
151
		);
152 1
	}
153
154
}
155