Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F1431148
EmptyMethodAndFunctionPlugin.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
3 KB
Referenced Files
None
Subscribers
None
EmptyMethodAndFunctionPlugin.php
View Options
<?php
declare
(
strict_types
=
1
);
use
ast\Node
;
use
Phan\Issue
;
use
Phan\Language\Element\Func
;
use
Phan\Language\Element\FunctionInterface
;
use
Phan\Language\Element\Method
;
use
Phan\Language\Element\Parameter
;
use
Phan\PluginV3
;
use
Phan\PluginV3\PluginAwarePostAnalysisVisitor
;
use
Phan\PluginV3\PostAnalyzeNodeCapability
;
/**
* Plugin which looks for empty methods/functions
*
* This Plugin hooks into one event;
*
* - getPostAnalyzeNodeVisitorClassName
* This method returns a class that is called on every AST node from every
* file being analyzed
*/
final
class
EmptyMethodAndFunctionPlugin
extends
PluginV3
implements
PostAnalyzeNodeCapability
{
public
static
function
getPostAnalyzeNodeVisitorClassName
():
string
{
return
EmptyMethodAndFunctionVisitor
::
class
;
}
}
/**
* Visit method/function/closure
*/
final
class
EmptyMethodAndFunctionVisitor
extends
PluginAwarePostAnalysisVisitor
{
/** @param Node $node a node of kind ast\AST_METHOD */
public
function
visitMethod
(
Node
$node
):
void
{
$stmts_node
=
$node
->
children
[
'stmts'
]
??
null
;
if
(!
$stmts_node
||
$stmts_node
->
children
)
{
return
;
}
$method
=
$this
->
context
->
getFunctionLikeInScope
(
$this
->
code_base
);
if
(!(
$method
instanceof
Method
))
{
throw
new
AssertionError
(
"Expected $method to be a method"
);
}
if
(
$method
->
isNewConstructor
())
{
foreach
(
$node
->
children
[
'params'
]->
children
as
$param
)
{
if
(
$param
instanceof
Node
&&
(
$param
->
flags
&
Parameter
::
PARAM_MODIFIER_VISIBILITY_FLAGS
))
{
// This uses constructor property promotion
return
;
}
}
}
if
(!
$method
->
isOverriddenByAnother
()
&&
!
$method
->
isOverride
()
&&
!
$method
->
isDeprecated
()
)
{
$this
->
emitIssue
(
self
::
getIssueTypeForEmptyMethod
(
$method
),
$node
->
lineno
,
$method
->
getRepresentationForIssue
()
);
}
}
public
function
visitFuncDecl
(
Node
$node
):
void
{
$this
->
analyzeFunction
(
$node
);
}
public
function
visitClosure
(
Node
$node
):
void
{
$this
->
analyzeFunction
(
$node
);
}
// No need for visitArrowFunc.
// By design, `fn($args) => expr` can't have an empty statement list because it must have an expression.
// It's always equivalent to `return expr;`
private
function
analyzeFunction
(
Node
$node
):
void
{
$stmts_node
=
$node
->
children
[
'stmts'
]
??
null
;
if
(
$stmts_node
&&
!
$stmts_node
->
children
)
{
$function
=
$this
->
context
->
getFunctionLikeInScope
(
$this
->
code_base
);
if
(!(
$function
instanceof
Func
))
{
throw
new
AssertionError
(
"Expected $function to be Func
\n
"
);
}
if
(!
$function
->
isDeprecated
())
{
$this
->
emitIssue
(
$function
->
isClosure
()
?
Issue
::
EmptyClosure
:
Issue
::
EmptyFunction
,
$node
->
lineno
,
$function
->
getRepresentationForIssue
()
);
}
}
}
private
static
function
getIssueTypeForEmptyMethod
(
FunctionInterface
$method
):
string
{
if
(!
$method
instanceof
Method
)
{
throw
new
\InvalidArgumentException
(
"
\$
method is not an instance of Method"
);
}
if
(
$method
->
isPrivate
())
{
return
Issue
::
EmptyPrivateMethod
;
}
if
(
$method
->
isProtected
())
{
return
Issue
::
EmptyProtectedMethod
;
}
return
Issue
::
EmptyPublicMethod
;
}
}
// Every plugin needs to return an instance of itself at the
// end of the file in which it's defined.
return
new
EmptyMethodAndFunctionPlugin
();
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sat, May 16, 20:07 (2 h, 30 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
66/56/fc16bb05063dc645969c803a01c2
Default Alt Text
EmptyMethodAndFunctionPlugin.php (3 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment