Skip to content

Fix NamespaceDirectoryNameSniff misreading strict_types as namespace name#333

Open
ewartx wants to merge 1 commit into
humanmade:mainfrom
ewartx:fix/issue-319-namespace-sniff-strict-types
Open

Fix NamespaceDirectoryNameSniff misreading strict_types as namespace name#333
ewartx wants to merge 1 commit into
humanmade:mainfrom
ewartx:fix/issue-319-namespace-sniff-strict-types

Conversation

@ewartx
Copy link
Copy Markdown

@ewartx ewartx commented May 15, 2026

Summary

Fixes #319.

NamespaceDirectoryNameSniff calls findNext( T_STRING, 0 ) on line 33 to locate the namespace name, which starts searching from position 0 of the file. When the file opens with a declare(strict_types=1); statement before its namespace declaration, the first T_STRING token in the file is strict_types (PHP's tokenizer emits the declare directive name as T_STRING), so the sniff reads strict_types as the namespace and reports a false NameMismatch or ExtraDirs error against the actual directory.

Fix

Change the findNext start position from 0 to $stackPtr, so the search begins at the T_NAMESPACE token the sniff is currently processing rather than the beginning of the file.

-		$name_ptr = $phpcsFile->findNext( T_STRING, 0);
+		$name_ptr = $phpcsFile->findNext( T_STRING, $stackPtr );

This matches the resolution proposed in #319 directly.

Why this is safe

The fix produces the same result as the existing code in every case except the buggy one:

  • Plain <?php namespace Foo; (no declare): the first T_STRING in the file is the namespace name itself, so the original (from position 0) and the fix (from $stackPtr) land on the same token.
  • <?php declare(strict_types=1); namespace Foo;: original reads strict_types; fix correctly reads Foo.
  • Multi-namespace namespace A {} namespace B {} files: original reads A for both invocations (the file-first T_STRING); fix correctly reads each block's own namespace name.

Only declare() directives can legally place a T_STRING token before T_NAMESPACE; PHP requires namespace to be the first non-declare statement, so other cases aren't reachable in real code.

Test

Adds HM/Tests/Files/NamespaceDirectoryNameUnitTest/inc/standards/strict-types-namespace.php to the existing fixture tree and adds its basename to the $pass list in NamespaceDirectoryNameUnitTest::getErrorList(). The fixture is the minimal repro from the issue:

<?php

declare(strict_types=1);

namespace HM\Coding\Standards\StrictTypesNamespace;

Verified locally with ./vendor/bin/phpunit --filter NamespaceDirectoryNameUnitTest:

  • Without the sniff fix, the new fixture fails: Expected 0 error(s) in strict-types-namespace.php but found 1 error(s). Directory /standards for namespace strict_types found; nested too deep. (HM.Files.NamespaceDirectoryName.ExtraDirs)
  • With the sniff fix, the full NamespaceDirectoryNameUnitTest passes.

…name

The sniff calls findNext(T_STRING, 0) on line 33 to locate the namespace name, which starts searching from position 0 of the file. When the file opens with a declare(strict_types=1) statement before its namespace declaration, the first T_STRING token in the file is strict_types (PHP tokenizes the declare directive name as T_STRING), so the sniff reads strict_types as the namespace and reports a false NameMismatch or ExtraDirs error against the actual directory.

Change the search start position to $stackPtr so the namespace name is read starting from the namespace keyword the sniff is currently processing.

Adds a fixture (strict-types-namespace.php) that combines strict_types with a namespace declaration; the test fails on the current main and passes with this fix.

Fixes humanmade#319.
@ewartx ewartx marked this pull request as ready for review May 15, 2026 18:52
@ewartx
Copy link
Copy Markdown
Author

ewartx commented May 15, 2026

@kadamwhite tagging you for visibility — this addresses the upstream NamespaceDirectoryNameSniff bug discussed in our wharton-humanmade PR #23 thread. Fix matches the resolution proposed in #319; local test run confirms it. Happy to iterate on anything.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NamespaceDirectoryNameSniff suggests strict_types in a subdirectory's file.

1 participant