Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,23 @@ protected function isReserved(string $name): bool {
return in_array($name, $this->reservedVariables, TRUE);
}

/**
* Check if a variable name has a leading underscore.
*
* Variables with leading underscores (e.g., $_static_value) are typically
* used as a naming convention for internal/special variables and should
* be excluded from naming convention checks.
*
* @param string $name
* Variable name (without $).
*
* @return bool
* TRUE if has leading underscore, FALSE otherwise.
*/
protected function hasLeadingUnderscore(string $name): bool {
return str_starts_with($name, '_');
}

/**
* Check if a variable name follows snake_case format.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ public function process(File $phpcsFile, $stackPtr): void {
return;
}

// Skip variables with leading underscores (e.g., $_static_value).
if ($this->hasLeadingUnderscore($var_name)) {
return;
}

// Skip static property accesses (self::$prop, static::$prop, etc.).
if ($this->isStaticPropertyAccess($phpcsFile, $stackPtr)) {
return;
Expand Down
5 changes: 5 additions & 0 deletions src/DrevOps/Sniffs/NamingConventions/ParameterNamingSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ public function process(File $phpcsFile, $stackPtr): void {
return;
}

// Skip variables with leading underscores (e.g., $_static_value).
if ($this->hasLeadingUnderscore($var_name)) {
return;
}

// Only process parameters (declaration only, not usage in body).
// Local variables handled by LocalVariableNamingSniff.
if (!$this->isParameter($phpcsFile, $stackPtr, FALSE)) {
Expand Down
22 changes: 21 additions & 1 deletion tests/Fixtures/Valid.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,17 @@
function functionWithValidSnakeCaseParams($valid_param_one, $valid_param_two) {
$valid_local_variable = 100;
$another_valid_local = $valid_local_variable * $valid_param_two;
return $valid_local_variable + $another_valid_local;
// Variables with leading underscores should be skipped.
$_static_value = 50;
$_internalVar = 25;
return $valid_local_variable + $another_valid_local + $_static_value + $_internalVar;
}

/**
* Function with underscore-prefixed parameter (should be skipped).
*/
function functionWithUnderscorePrefixedParam($_prefixed_param) {
return $_prefixed_param * 2;
}

class ClassWithValidSnakeCaseNaming {
Expand All @@ -16,7 +26,17 @@ class ClassWithValidSnakeCaseNaming {

public function methodWithValidSnakeCaseParam($valid_param) {
$valid_local_variable = strtolower($valid_param);
// Variables with leading underscores should be skipped.
$_internal_cache = [];
$_tempValue = NULL;
return $valid_local_variable;
}

/**
* Method with underscore-prefixed parameter (should be skipped).
*/
public function methodWithUnderscorePrefixedParam($_prefixed_param) {
return $_prefixed_param;
}

}
38 changes: 38 additions & 0 deletions tests/Unit/AbstractVariableNamingSniffTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -683,4 +683,42 @@ public function testToFormatThrowsExceptionForInvalidFormat(): void {
$method->invoke($sniff, 'test');
}

/**
* Test leading underscore detection.
*
* @param string $name
* The variable name to test.
* @param bool $expected
* Expected result.
*/
#[DataProvider('providerHasLeadingUnderscore')]
public function testHasLeadingUnderscore(string $name, bool $expected): void {
$sniff = new LocalVariableNamingSniff();
$reflection = new \ReflectionClass($sniff);
$method = $reflection->getMethod('hasLeadingUnderscore');

$result = $method->invoke($sniff, $name);
$this->assertSame($expected, $result, 'Failed for: ' . $name);
}

/**
* Data provider for hasLeadingUnderscore tests.
*
* @return array<string, array<string|bool>>
* Test cases.
*/
public static function providerHasLeadingUnderscore(): array {
return [
'leading_underscore_snake' => ['_static_value', TRUE],
'leading_underscore_camel' => ['_staticValue', TRUE],
'leading_underscore_only' => ['_', TRUE],
'leading_double_underscore' => ['__internal', TRUE],
'no_leading_underscore_snake' => ['static_value', FALSE],
'no_leading_underscore_camel' => ['staticValue', FALSE],
'underscore_in_middle' => ['static_value', FALSE],
'trailing_underscore' => ['value_', FALSE],
'single_letter' => ['a', FALSE],
];
}

}
8 changes: 8 additions & 0 deletions tests/Unit/LocalVariableNamingSniffTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,14 @@ public static function dataProviderProcess(): array {
'<?php class Test { public function test() { $value = $this->camelCaseProperty; } }',
FALSE,
],
'underscore_prefixed_variable' => [
'<?php function test() { $_static_value = 1; }',
FALSE,
],
'underscore_prefixed_variable_camel' => [
'<?php function test() { $_internalVar = 1; }',
FALSE,
],
];
}

Expand Down
8 changes: 8 additions & 0 deletions tests/Unit/ParameterNamingSniffTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ public static function dataProviderProcess(): array {
'<?php class Test extends BaseClass { public function test($invalidParam) {} }',
FALSE,
],
'underscore_prefixed_parameter' => [
'<?php function test($_prefixed_param) {}',
FALSE,
],
'underscore_prefixed_parameter_camel' => [
'<?php function test($_prefixedParam) {}',
FALSE,
],
];
}

Expand Down
Loading