<commit_before><?php
namespace Psalm\Internal\Analyzer\Statements\Expression;

use PhpParser;
use Psalm\Internal\Analyzer\CommentAnalyzer;
use Psalm\Internal\Analyzer\Statements\Block\ForeachAnalyzer;
use Psalm\Internal\Analyzer\Statements\Expression\Assignment\ArrayAssignmentAnalyzer;
use Psalm\Internal\Analyzer\Statements\Expression\Assignment\PropertyAssignmentAnalyzer;
use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer;
use Psalm\Internal\Analyzer\StatementsAnalyzer;
use Psalm\Internal\Analyzer\TypeAnalyzer;
use Psalm\CodeLocation;
use Psalm\Context;
use Psalm\Exception\DocblockParseException;
use Psalm\Exception\IncorrectDocblockException;
use Psalm\Internal\FileManipulation\FileManipulationBuffer;
use Psalm\Issue\AssignmentToVoid;
use Psalm\Issue\ImpureByReferenceAssignment;
use Psalm\Issue\ImpurePropertyAssignment;
use Psalm\Issue\InvalidArrayOffset;
use Psalm\Issue\InvalidDocblock;
use Psalm\Issue\InvalidScope;
use Psalm\Issue\LoopInvalidation;
use Psalm\Issue\MissingDocblockType;
use Psalm\Issue\MixedAssignment;
use Psalm\Issue\NoValue;
use Psalm\Issue\PossiblyUndefinedArrayOffset;
use Psalm\Issue\ReferenceConstraintViolation;
use Psalm\Issue\UnnecessaryVarAnnotation;
use Psalm\IssueBuffer;
use Psalm\Type;
use function is_string;
use function strpos;
use function strtolower;

/**
 * @internal
 */
class AssignmentAnalyzer
{
    /**
     * @param  StatementsAnalyzer        $statements_analyzer
     * @param  PhpParser\Node\Expr      $assign_var
     * @param  PhpParser\Node\Expr|null $assign_value  This has to be null to support list destructuring
     * @param  Type\Union|null          $assign_value_type
     * @param  Context                  $context
     * @param  ?PhpParser\Comment\Doc   $doc_comment
     *
     * @return false|Type\Union
     */
    public static function analyze(
        StatementsAnalyzer $statements_analyzer,
        PhpParser\Node\Expr $assign_var,
        $assign_value,
        $assign_value_type,
        Context $context,
        ?PhpParser\Comment\Doc $doc_comment
    ) {
        $var_id = ExpressionAnalyzer::getVarId(
            $assign_var,
            $statements_analyzer->getFQCLN(),
            $statements_analyzer
        );

        // gets a variable id that *may* contain array keys
        $array_var_id = ExpressionAnalyzer::getArrayVarId(
            $assign_var,
            $statements_analyzer->getFQCLN(),
            $statements_analyzer
        );

        $var_comments = [];
        $comment_type = null;
        $comment_type_location = null;

        $was_in_assignment = $context->inside_assignment;

        $context->inside_assignment = true;

        $codebase = $statements_analyzer->getCodebase();

        $remove_taint = false;

        if ($doc_comment) {
            $file_path = $statements_analyzer->getRootFilePath();

            $file_storage_provider = $codebase->file_storage_provider;

            $file_storage = $file_storage_provider->get($file_path);

            $template_type_map = $statements_analyzer->getTemplateTypeMap();

            try {
                $var_comments = CommentAnalyzer::getTypeFromComment(
                    $doc_comment,
                    $statements_analyzer->getSource(),
                    $statements_analyzer->getAliases(),
                    $template_type_map,
                    $file_storage->type_aliases
                );
            } catch (IncorrectDocblockException $e) {
                if (IssueBuffer::accepts(
                    new MissingDocblockType(
                        (string)$e->getMessage(),
                        new CodeLocation($statements_analyzer->getSource(), $assign_var)
                    )
                )) {
                    // fall through
                }
            } catch (DocblockParseException $e) {
                if (IssueBuffer::accepts(
                    new InvalidDocblock(
                        (string)$e->getMessage(),
                        new CodeLocation($statements_analyzer->getSource(), $assign_var)
                    )
                )) {
                    // fall through
                }
            }

            foreach ($var_comments as $var_comment) {
                if ($var_comment->remove_taint) {
                    $remove_taint = true;
                }

                if (!$var_comment->type) {
                    continue;
                }

                try {
                    $var_comment_type = ExpressionAnalyzer::fleshOutType(
                        $codebase,
                        $var_comment->type,
                        $context->self,
                        $context->self,
                        $statements_analyzer->getParentFQCLN()
                    );

                    $var_comment_type->setFromDocblock();

                    $var_comment_type->check(
                        $statements_analyzer,
                        new CodeLocation($statements_analyzer->getSource(), $assign_var),
                        $statements_analyzer->getSuppressedIssues()
                    );

                    $type_location = null;

                    if ($var_comment->type_start
                        && $var_comment->type_end
                        && $var_comment->line_number
                    ) {
                        $type_location = new CodeLocation\DocblockTypeLocation(
                            $statements_analyzer,
                            $var_comment->type_start,
                            $var_comment->type_end,
                            $var_comment->line_number
                        );

                        if ($codebase->alter_code) {
                            $codebase->classlikes->handleDocblockTypeInMigration(
                                $codebase,
                                $statements_analyzer,
                                $var_comment_type,
                                $type_location,
                                $context->calling_function_id
                            );
                        }
                    }<commit_msg>Docblock-provided type is not inferred<commit_after><?php
namespace Psalm\Internal\Analyzer\Statements\Expression;

use PhpParser;
use Psalm\Internal\Analyzer\CommentAnalyzer;
use Psalm\Internal\Analyzer\Statements\Block\ForeachAnalyzer;
use Psalm\Internal\Analyzer\Statements\Expression\Assignment\ArrayAssignmentAnalyzer;
use Psalm\Internal\Analyzer\Statements\Expression\Assignment\PropertyAssignmentAnalyzer;
use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer;
use Psalm\Internal\Analyzer\StatementsAnalyzer;
use Psalm\Internal\Analyzer\TypeAnalyzer;
use Psalm\CodeLocation;
use Psalm\Context;
use Psalm\Exception\DocblockParseException;
use Psalm\Exception\IncorrectDocblockException;
use Psalm\Internal\FileManipulation\FileManipulationBuffer;
use Psalm\Issue\AssignmentToVoid;
use Psalm\Issue\ImpureByReferenceAssignment;
use Psalm\Issue\ImpurePropertyAssignment;
use Psalm\Issue\InvalidArrayOffset;
use Psalm\Issue\InvalidDocblock;
use Psalm\Issue\InvalidScope;
use Psalm\Issue\LoopInvalidation;
use Psalm\Issue\MissingDocblockType;
use Psalm\Issue\MixedAssignment;
use Psalm\Issue\NoValue;
use Psalm\Issue\PossiblyUndefinedArrayOffset;
use Psalm\Issue\ReferenceConstraintViolation;
use Psalm\Issue\UnnecessaryVarAnnotation;
use Psalm\IssueBuffer;
use Psalm\Type;
use function is_string;
use function strpos;
use function strtolower;

/**
 * @internal
 */
class AssignmentAnalyzer
{
    /**
     * @param  StatementsAnalyzer        $statements_analyzer
     * @param  PhpParser\Node\Expr      $assign_var
     * @param  PhpParser\Node\Expr|null $assign_value  This has to be null to support list destructuring
     * @param  Type\Union|null          $assign_value_type
     * @param  Context                  $context
     * @param  ?PhpParser\Comment\Doc   $doc_comment
     *
     * @return false|Type\Union
     */
    public static function analyze(
        StatementsAnalyzer $statements_analyzer,
        PhpParser\Node\Expr $assign_var,
        $assign_value,
        $assign_value_type,
        Context $context,
        ?PhpParser\Comment\Doc $doc_comment
    ) {
        $var_id = ExpressionAnalyzer::getVarId(
            $assign_var,
            $statements_analyzer->getFQCLN(),
            $statements_analyzer
        );

        // gets a variable id that *may* contain array keys
        $array_var_id = ExpressionAnalyzer::getArrayVarId(
            $assign_var,
            $statements_analyzer->getFQCLN(),
            $statements_analyzer
        );

        $var_comments = [];
        $comment_type = null;
        $comment_type_location = null;

        $was_in_assignment = $context->inside_assignment;

        $context->inside_assignment = true;

        $codebase = $statements_analyzer->getCodebase();

        $remove_taint = false;

        if ($doc_comment) {
            $file_path = $statements_analyzer->getRootFilePath();

            $file_storage_provider = $codebase->file_storage_provider;

            $file_storage = $file_storage_provider->get($file_path);

            $template_type_map = $statements_analyzer->getTemplateTypeMap();

            try {
                $var_comments = CommentAnalyzer::getTypeFromComment(
                    $doc_comment,
                    $statements_analyzer->getSource(),
                    $statements_analyzer->getAliases(),
                    $template_type_map,
                    $file_storage->type_aliases
                );
            } catch (IncorrectDocblockException $e) {
                if (IssueBuffer::accepts(
                    new MissingDocblockType(
                        (string)$e->getMessage(),
                        new CodeLocation($statements_analyzer->getSource(), $assign_var)
                    )
                )) {
                    // fall through
                }
            } catch (DocblockParseException $e) {
                if (IssueBuffer::accepts(
                    new InvalidDocblock(
                        (string)$e->getMessage(),
                        new CodeLocation($statements_analyzer->getSource(), $assign_var)
                    )
                )) {
                    // fall through
                }
            }

            foreach ($var_comments as $var_comment) {
                if ($var_comment->remove_taint) {
                    $remove_taint = true;
                }

                if (!$var_comment->type) {
                    continue;
                }

                try {
                    $var_comment_type = ExpressionAnalyzer::fleshOutType(
                        $codebase,
                        $var_comment->type,
                        $context->self,
                        $context->self,
                        $statements_analyzer->getParentFQCLN()
                    );

                    $var_comment_type->setFromDocblock();

                    $var_comment_type->check(
                        $statements_analyzer,
                        new CodeLocation($statements_analyzer->getSource(), $assign_var),
                        $statements_analyzer->getSuppressedIssues(),
                        [],
                        false
                    );

                    $type_location = null;

                    if ($var_comment->type_start
                        && $var_comment->type_end
                        && $var_comment->line_number
                    ) {
                        $type_location = new CodeLocation\DocblockTypeLocation(
                            $statements_analyzer,
                            $var_comment->type_start,
                            $var_comment->type_end,
                            $var_comment->line_number
                        );

                        if ($codebase->alter_code) {
                            $codebase->classlikes->handleDocblockTypeInMigration(
                                $codebase,
                                $statements_analyzer,
                                $var_comment_type,
                                $type_location,
                                $context->calling_function_id
                            );
                        }
                    }
{'fraction_non_alphanumeric': 0.08460663198959688, 'fraction_numerical': 0.0, 'mean_word_length': 1.636032562125107, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 75, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7061227', 'n_tokens_mistral': 3330, 'n_tokens_neox': 3067, 'n_words': 479}