33namespace PHPStan \Rules \Classes ;
44
55use PhpParser \Node ;
6- use PhpParser \Node \Stmt \ClassConst ;
7- use PhpParser \Node \Stmt \EnumCase ;
86use PHPStan \Analyser \Scope ;
97use PHPStan \DependencyInjection \RegisteredRule ;
108use PHPStan \Node \InClassNode ;
119use PHPStan \Rules \Rule ;
12- use PHPStan \Rules \RuleErrorBuilder ;
13- use PHPStan \ShouldNotHappenException ;
14- use function array_key_exists ;
15- use function is_string ;
16- use function sprintf ;
1710use function strtolower ;
1811
1912/**
2316final class DuplicateDeclarationRule implements Rule
2417{
2518
19+ public function __construct (private DuplicateDeclarationHelper $ helper )
20+ {
21+ }
22+
2623 public function getNodeType (): string
2724 {
2825 return InClassNode::class;
@@ -32,104 +29,11 @@ public function processNode(Node $node, Scope $scope): array
3229 {
3330 $ classReflection = $ node ->getClassReflection ();
3431
35- $ identifierType = strtolower ($ classReflection ->getClassTypeDescription ());
36-
37- $ errors = [];
38-
39- $ declaredClassConstantsOrEnumCases = [];
40- foreach ($ node ->getOriginalNode ()->stmts as $ stmtNode ) {
41- if ($ stmtNode instanceof EnumCase) {
42- if (array_key_exists ($ stmtNode ->name ->name , $ declaredClassConstantsOrEnumCases )) {
43- $ errors [] = RuleErrorBuilder::message (sprintf (
44- 'Cannot redeclare enum case %s::%s. ' ,
45- $ classReflection ->getDisplayName (),
46- $ stmtNode ->name ->name ,
47- ))->identifier (sprintf ('%s.duplicateEnumCase ' , $ identifierType ))
48- ->line ($ stmtNode ->getStartLine ())
49- ->nonIgnorable ()
50- ->build ();
51- } else {
52- $ declaredClassConstantsOrEnumCases [$ stmtNode ->name ->name ] = true ;
53- }
54- } elseif ($ stmtNode instanceof ClassConst) {
55- foreach ($ stmtNode ->consts as $ classConstNode ) {
56- if (array_key_exists ($ classConstNode ->name ->name , $ declaredClassConstantsOrEnumCases )) {
57- $ errors [] = RuleErrorBuilder::message (sprintf (
58- 'Cannot redeclare constant %s::%s. ' ,
59- $ classReflection ->getDisplayName (),
60- $ classConstNode ->name ->name ,
61- ))->identifier (sprintf ('%s.duplicateConstant ' , $ identifierType ))
62- ->line ($ classConstNode ->getStartLine ())
63- ->nonIgnorable ()
64- ->build ();
65- } else {
66- $ declaredClassConstantsOrEnumCases [$ classConstNode ->name ->name ] = true ;
67- }
68- }
69- }
70- }
71-
72- $ declaredProperties = [];
73- foreach ($ node ->getOriginalNode ()->getProperties () as $ propertyDecl ) {
74- foreach ($ propertyDecl ->props as $ property ) {
75- if (array_key_exists ($ property ->name ->name , $ declaredProperties )) {
76- $ errors [] = RuleErrorBuilder::message (sprintf (
77- 'Cannot redeclare property %s::$%s. ' ,
78- $ classReflection ->getDisplayName (),
79- $ property ->name ->name ,
80- ))->identifier (sprintf ('%s.duplicateProperty ' , $ identifierType ))
81- ->line ($ property ->getStartLine ())
82- ->nonIgnorable ()
83- ->build ();
84- } else {
85- $ declaredProperties [$ property ->name ->name ] = true ;
86- }
87- }
88- }
89-
90- $ declaredFunctions = [];
91- foreach ($ node ->getOriginalNode ()->getMethods () as $ method ) {
92- if ($ method ->name ->toLowerString () === '__construct ' ) {
93- foreach ($ method ->params as $ param ) {
94- if ($ param ->flags === 0 ) {
95- continue ;
96- }
97-
98- if (!$ param ->var instanceof Node \Expr \Variable || !is_string ($ param ->var ->name )) {
99- throw new ShouldNotHappenException ();
100- }
101-
102- $ propertyName = $ param ->var ->name ;
103-
104- if (array_key_exists ($ propertyName , $ declaredProperties )) {
105- $ errors [] = RuleErrorBuilder::message (sprintf (
106- 'Cannot redeclare property %s::$%s. ' ,
107- $ classReflection ->getDisplayName (),
108- $ propertyName ,
109- ))->identifier (sprintf ('%s.duplicateProperty ' , $ identifierType ))
110- ->line ($ param ->getStartLine ())
111- ->nonIgnorable ()
112- ->build ();
113- } else {
114- $ declaredProperties [$ propertyName ] = true ;
115- }
116- }
117- }
118- if (array_key_exists (strtolower ($ method ->name ->name ), $ declaredFunctions )) {
119- $ errors [] = RuleErrorBuilder::message (sprintf (
120- 'Cannot redeclare method %s::%s(). ' ,
121- $ classReflection ->getDisplayName (),
122- $ method ->name ->name ,
123- ))->identifier (sprintf ('%s.duplicateMethod ' , $ identifierType ))
124- ->line ($ method ->getStartLine ())
125- ->nonIgnorable ()
126- ->build ();
127- } else {
128- $ declaredFunctions [strtolower ($ method ->name ->name )] = true ;
129- }
130- }
131-
132- return $ errors ;
32+ return $ this ->helper ->checkClassLike (
33+ $ node ->getOriginalNode (),
34+ $ classReflection ->getDisplayName (),
35+ strtolower ($ classReflection ->getClassTypeDescription ()),
36+ );
13337 }
13438
13539}
0 commit comments