Skip to content

Commit

Permalink
psalm min v3.17 (#95)
Browse files Browse the repository at this point in the history
* psalm min v3.17

* no message

* no message
  • Loading branch information
seferov authored Oct 14, 2020
1 parent 1978eda commit fc1bcd6
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 36 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"php": "^7.1",
"ext-simplexml": "*",
"symfony/framework-bundle": "^3.0 || ^4.0 || ^5.0",
"vimeo/psalm": "^3.16 <3.17"
"vimeo/psalm": "^3.17"
},
"require-dev": {
"doctrine/orm": "^2.7",
Expand Down
9 changes: 9 additions & 0 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="3.17.1@8f211792d813e4dc89f04ed372785ce93b902fd1">
<file src="src/Twig/Context.php">
<UnnecessaryVarAnnotation occurrences="2">
<code>int</code>
<code>string</code>
</UnnecessaryVarAnnotation>
</file>
</files>
1 change: 1 addition & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
cacheDirectory=".build/psalm"
errorBaseline="psalm-baseline.xml"
>
<projectFiles>
<directory name="src" />
Expand Down
3 changes: 1 addition & 2 deletions src/Handler/ContainerHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
use Psalm\SymfonyPsalmPlugin\Symfony\ContainerMeta;
use Psalm\Type\Atomic\TNamedObject;
use Psalm\Type\Union;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;

class ContainerHandler implements AfterMethodCallAnalysisInterface, AfterClassLikeVisitInterface
{
Expand Down Expand Up @@ -105,7 +104,7 @@ public static function afterMethodCallAnalysis(
}

if (!$service->isPublic()) {
$isTestContainer = $context->parent && (KernelTestCase::class === $context->parent || is_subclass_of($context->parent, KernelTestCase::class));
$isTestContainer = $context->parent && ('Symfony\Bundle\FrameworkBundle\Test\KernelTestCase' === $context->parent || is_subclass_of($context->parent, 'Symfony\Bundle\FrameworkBundle\Test\KernelTestCase'));
if (!$isTestContainer) {
IssueBuffer::accepts(
new PrivateService($serviceId, new CodeLocation($statements_source, $expr->args[0]->value)),
Expand Down
6 changes: 3 additions & 3 deletions src/Twig/AnalyzedTemplatesTainter.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class AnalyzedTemplatesTainter implements AfterMethodCallAnalysisInterface
public static function afterMethodCallAnalysis(Expr $expr, string $method_id, string $appearing_method_id, string $declaring_method_id, Context $context, StatementsSource $statements_source, Codebase $codebase, array &$file_replacements = [], Union &$return_type_candidate = null): void
{
if (
null === $codebase->taint
null === $codebase->taint_flow_graph
|| !$expr instanceof MethodCall || $method_id !== Environment::class.'::render' || empty($expr->args)
|| !isset($expr->args[0]->value) || !$expr->args[0]->value instanceof String_
|| !isset($expr->args[1]->value) || !$expr->args[1]->value instanceof Array_
Expand All @@ -35,7 +35,7 @@ public static function afterMethodCallAnalysis(Expr $expr, string $method_id, st
$template_name = $expr->args[0]->value->value;
$twig_arguments_type = $statements_source->getNodeTypeProvider()->getType($expr->args[1]->value);

if (null === $twig_arguments_type || null === $twig_arguments_type->parent_nodes) {
if (null === $twig_arguments_type) {
return;
}

Expand All @@ -44,7 +44,7 @@ public static function afterMethodCallAnalysis(Expr $expr, string $method_id, st
$sink_taint = TemplateFileAnalyzer::getTaintNodeForTwigNamedVariable(
$template_name, $matches[1]
);
$codebase->taint->addPath($source_taint, $sink_taint, 'arg');
$codebase->taint_flow_graph->addPath($source_taint, $sink_taint, 'arg');
}
}
}
46 changes: 24 additions & 22 deletions src/Twig/Context.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
namespace Psalm\SymfonyPsalmPlugin\Twig;

use Psalm\CodeLocation;
use Psalm\Internal\Codebase\Taint;
use Psalm\Internal\Taint\Sink;
use Psalm\Internal\Taint\Taintable;
use Psalm\Internal\Taint\TaintNode;
use Psalm\Internal\Codebase\TaintFlowGraph;
use Psalm\Internal\ControlFlow\ControlFlowNode;
use Psalm\Internal\ControlFlow\TaintSink;
use Psalm\Internal\ControlFlow\TaintSource;
use Psalm\Type\TaintKind;
use Twig\Node\Expression\FilterExpression;
use Twig\Node\Expression\NameExpression;
Expand All @@ -18,25 +18,25 @@

class Context
{
/** @var array<string, Taintable> */
/** @var array<string, ControlFlowNode> */
private $unassignedVariables = [];

/** @var array<string, Taintable> */
/** @var array<string, ControlFlowNode> */
private $localVariables = [];

/** @var Source */
private $sourceContext;

/** @var Taint */
/** @var TaintFlowGraph */
private $taint;

public function __construct(Source $sourceContext, Taint $taint)
public function __construct(Source $sourceContext, TaintFlowGraph $taint)
{
$this->sourceContext = $sourceContext;
$this->taint = $taint;
}

public function addSink(Node $node, Taintable $source): void
public function addSink(Node $node, ControlFlowNode $source): void
{
$codeLocation = $this->getNodeLocation($node);

Expand All @@ -45,7 +45,7 @@ public function addSink(Node $node, Taintable $source): void
$sinkName = 'twig_print';
}

$sink = Sink::getForMethodArgument(
$sink = TaintSink::getForMethodArgument(
$sinkName, $sinkName, 0, null, $codeLocation
);

Expand All @@ -59,28 +59,28 @@ public function addSink(Node $node, Taintable $source): void
$this->taint->addPath($source, $sink, 'arg');
}

public function taintVariable(NameExpression $expression): Taintable
public function taintVariable(NameExpression $expression): ControlFlowNode
{
/** @var string $variableName */
$variableName = $expression->getAttribute('name');

$sinkNode = TaintNode::getForAssignment($variableName, $this->getNodeLocation($expression));
$sinkNode = TaintSource::getForAssignment($variableName, $this->getNodeLocation($expression));

$this->taint->addTaintNode($sinkNode);
$this->taint->addNode($sinkNode);
$sinkNode = $this->addVariableTaintNode($expression);

return $this->addVariableUsage($variableName, $sinkNode);
}

public function getTaintDestination(Taintable $taintSource, FilterExpression $expression): TaintNode
public function getTaintDestination(ControlFlowNode $taintSource, FilterExpression $expression): ControlFlowNode
{
/** @var string $filterName */
$filterName = $expression->getNode('filter')->getAttribute('value');

$returnLocation = $this->getNodeLocation($expression);
$taintDestination = TaintNode::getForMethodReturn('filter_'.$filterName, 'filter_'.$filterName, $returnLocation, $returnLocation);
$taintDestination = TaintSource::getForMethodReturn('filter_'.$filterName, 'filter_'.$filterName, $returnLocation, $returnLocation);

$this->taint->addTaintNode($taintDestination);
$this->taint->addNode($taintDestination);
$this->taint->addPath($taintSource, $taintDestination, 'arg');

return $taintDestination;
Expand Down Expand Up @@ -110,25 +110,25 @@ public function taintUnassignedVariables(string $templateName): void
{
foreach ($this->unassignedVariables as $variableName => $taintable) {
$label = strtolower($templateName).'#'.strtolower($variableName);
$taintSource = new TaintNode($label, $label, null, null);
$taintSource = new TaintSource($label, $label, null, null);

$this->taint->addTaintNode($taintSource);
$this->taint->addNode($taintSource);
$this->taint->addPath($taintSource, $taintable, 'arg');
}
}

private function addVariableTaintNode(NameExpression $variableNode): TaintNode
private function addVariableTaintNode(NameExpression $variableNode): ControlFlowNode
{
/** @var string $variableName */
$variableName = $variableNode->getAttribute('name');
$taintNode = TaintNode::getForAssignment($variableName, $this->getNodeLocation($variableNode));
$taintNode = TaintSource::getForAssignment($variableName, $this->getNodeLocation($variableNode));

$this->taint->addTaintNode($taintNode);
$this->taint->addNode($taintNode);

return $taintNode;
}

private function addVariableUsage(string $variableName, Taintable $variableTaint): Taintable
private function addVariableUsage(string $variableName, ControlFlowNode $variableTaint): ControlFlowNode
{
if (!isset($this->localVariables[$variableName])) {
return $this->unassignedVariables[$variableName] = $variableTaint;
Expand All @@ -139,10 +139,12 @@ private function addVariableUsage(string $variableName, Taintable $variableTaint

private function getNodeLocation(Node $node): CodeLocation
{
/** @psalm-var string $fileName */
$fileName = $this->sourceContext->getName();
$filePath = $this->sourceContext->getPath();
$snippet = $this->sourceContext->getCode(); // warning : the getCode method returns the whole template, not only the statement
$fileCode = file_get_contents($filePath);
/** @psalm-var int $lineNumber */
$lineNumber = $node->getTemplateLine();
$lines = explode("\n", $fileCode);

Expand Down
4 changes: 2 additions & 2 deletions src/Twig/PrintNodeAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Psalm\SymfonyPsalmPlugin\Twig;

use Psalm\Internal\Taint\Taintable;
use Psalm\Internal\ControlFlow\ControlFlowNode;
use RuntimeException;
use Twig\Node\Expression\AbstractExpression;
use Twig\Node\Expression\FilterExpression;
Expand Down Expand Up @@ -47,7 +47,7 @@ private function expressionIsEscaped(AbstractExpression $expression): bool
return false;
}

private function getTaintSource(AbstractExpression $expression): ?Taintable
private function getTaintSource(AbstractExpression $expression): ?ControlFlowNode
{
if ($expression instanceof FilterExpression) {
/** @var AbstractExpression $filteredExpression */
Expand Down
11 changes: 5 additions & 6 deletions src/Twig/TemplateFileAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use Psalm\Context as PsalmContext;
use Psalm\Internal\Analyzer\FileAnalyzer;
use Psalm\Internal\Taint\TaintNode;
use Psalm\Internal\ControlFlow\TaintSource;
use Twig\Environment;
use Twig\Loader\FilesystemLoader;
use Twig\NodeTraverser;
Expand All @@ -19,13 +19,12 @@ public function analyze(
PsalmContext $global_context = null
) {
$codebase = $this->project_analyzer->getCodebase();
$taint = $codebase->taint_flow_graph;

if (null === $codebase->taint) {
if (null === $taint) {
return;
}

$taint = $codebase->taint;

$loader = new FilesystemLoader('templates', $codebase->config->base_dir);
$twig = new Environment($loader, [
'cache' => false,
Expand Down Expand Up @@ -53,9 +52,9 @@ public function analyze(
public static function getTaintNodeForTwigNamedVariable(
string $template_id,
string $variable_name
): TaintNode {
): TaintSource {
$label = $arg_id = strtolower($template_id).'#'.strtolower($variable_name);

return new TaintNode($arg_id, $label, null, null);
return new TaintSource($arg_id, $label, null, null);
}
}

0 comments on commit fc1bcd6

Please sign in to comment.