Skip to content

Commit

Permalink
Variables should outlive namespaces (#8779)
Browse files Browse the repository at this point in the history
Variables in PHP are not namespaced. In other words, namespaces share
the context with the file they are located in.

See https://3v4l.org/2qvrC

Fixes #8778
  • Loading branch information
weirdan committed Nov 27, 2022
1 parent 05b8e0e commit 8fa35c2
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 13 deletions.
17 changes: 9 additions & 8 deletions src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php
Expand Up @@ -87,16 +87,17 @@ public function collectAnalyzableInformation(): void

if ($leftover_stmts) {
$statements_analyzer = new StatementsAnalyzer($this, new NodeDataProvider());
$context = new Context();
$context->is_global = true;
$context->defineGlobals();
$context->collect_exceptions = $codebase->config->check_for_throws_in_global_scope;
$statements_analyzer->analyze($leftover_stmts, $context, null, true);

$file_context = $this->source->context;
if ($file_context) {
$file_context->mergeExceptions($context);

if ($file_context !== null) {
$context = $file_context;
} else {
$context = new Context();
$context->is_global = true;
$context->defineGlobals();
$context->collect_exceptions = $codebase->config->check_for_throws_in_global_scope;
}
$statements_analyzer->analyze($leftover_stmts, $context, null, true);
}
}

Expand Down
13 changes: 8 additions & 5 deletions tests/Config/ConfigTest.php
Expand Up @@ -152,7 +152,7 @@ public function testIgnoreMissingProjectDirectory(): void
$config = $this->project_analyzer->getConfig();

$this->assertTrue($config->isInProjectDirs(realpath('src/Psalm/Type.php')));
$this->assertFalse($config->isInProjectDirs(realpath(__DIR__.'/../../').'/does/not/exist/FileAnalyzer.php'));
$this->assertFalse($config->isInProjectDirs(realpath(__DIR__ . '/../../') . '/does/not/exist/FileAnalyzer.php'));
$this->assertFalse($config->isInProjectDirs(realpath('examples/TemplateScanner.php')));
}

Expand Down Expand Up @@ -1159,15 +1159,18 @@ function example1(): void {
ord($_GET["str"]);
}
$glob1 = 0;
error_reporting($glob1);
$z = $glob1;
$z = 0;
error_reporting($z);
$old = $_GET["str"];
$_GET["str"] = 0;
error_reporting($_GET["str"]);
$_GET["str"] = $old;
function example2(): void {
global $glob1, $glob2, $glob3;
error_reporting($glob1);
global $z, $glob2, $glob3;
error_reporting($z);
ord($glob2["str"]);
$glob3->func();
ord($_GET["str"]);
Expand Down
18 changes: 18 additions & 0 deletions tests/NamespaceTest.php
Expand Up @@ -71,6 +71,24 @@ function foo() : void {
$c = $argv;
}',
],
'varsAreNotScoped' => [
'code' => '<?php
namespace A {
$a = "1";
}
namespace B\C {
$bc = "2";
}
namespace {
echo $a . PHP_EOL;
echo $bc . PHP_EOL;
}
',
'assertions' => [
'$a===' => "'1'",
'$bc===' => "'2'",
],
],
];
}

Expand Down

0 comments on commit 8fa35c2

Please sign in to comment.