Skip to content

Commit

Permalink
Variables should outlive namespaces
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 vimeo#8778
  • Loading branch information
weirdan committed Nov 27, 2022
1 parent 1819a2d commit 38c6821
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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 38c6821

Please sign in to comment.