Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

non-existent service "locale.plural.formula" #11

Closed
FlorentTorregrosa opened this issue Jan 4, 2023 · 6 comments
Closed

non-existent service "locale.plural.formula" #11

FlorentTorregrosa opened this issue Jan 4, 2023 · 6 comments

Comments

@FlorentTorregrosa
Copy link
Contributor

Hi,

On either Drupal 9 and Drupal 10 with the latest version of psalm drupal plugin, when trying to scan files. I get this error.

I have rolled back on 48e3cbc (the version before recent changes). And I also obtain the error.

So I guess this is due to an update in Symfony?

Target PHP version: 8.1 (inferred from current PHP version)
Scanning files...
Analyzing files...

░░Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service "locale.plural.formula". in /project/vendor/symfony/dependency-injection/ContainerBuilder.php on line 935 #0 /project/vendor/psalm/plugin-symfony/src/Symfony/ContainerMeta.php(155): Symfony\Component\DependencyInjection\ContainerBuilder->getDefinition('locale.plural.f...')
#1 /project/vendor/psalm/plugin-symfony/src/Symfony/ContainerMeta.php(64): Psalm\SymfonyPsalmPlugin\Symfony\ContainerMeta->getDefinition('locale.plural.f...')
#2 /project/vendor/mortenson/psalm-plugin-drupal/ContainerHandler.php(59): Psalm\SymfonyPsalmPlugin\Symfony\ContainerMeta->get('locale.plural.f...')
#3 /project/vendor/vimeo/psalm/src/Psalm/Internal/EventDispatcher.php(319): mortenson\PsalmPluginDrupal\ContainerHandler::afterMethodCallAnalysis(Object(PhpParser\Node\Expr\StaticCall), 'Drupal::service', 'Drupal::service', 'Drupal::service', Object(Psalm\Context), Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(Psalm\Codebase), Array, Object(Psalm\Type\Union))
#4 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/ExistingAtomicStaticCallAnalyzer.php(409): Psalm\Internal\EventDispatcher->dispatchAfterMethodCallAnalysis(Object(Psalm\Plugin\EventHandler\Event\AfterMethodCallAnalysisEvent))
#5 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php(877): Psalm\Internal\Analyzer\Statements\Expression\Call\StaticMethod\ExistingAtomicStaticCallAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\StaticCall), Object(PhpParser\Node\Identifier), Array, Object(Psalm\Context), Object(Psalm\Type\Atomic\TNamedObject), Object(Psalm\Internal\MethodIdentifier), 'Drupal::service', Object(Psalm\Storage\ClassLikeStorage), false)
#6 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php(202): Psalm\Internal\Analyzer\Statements\Expression\Call\StaticMethod\AtomicStaticCallAnalyzer::handleNamedCall(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\StaticCall), Object(PhpParser\Node\Identifier), Object(Psalm\Context), Object(Psalm\Type\Atomic\TNamedObject), Array, 'Drupal', false, true)
#7 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticCallAnalyzer.php(215): Psalm\Internal\Analyzer\Statements\Expression\Call\StaticMethod\AtomicStaticCallAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\StaticCall), Object(Psalm\Context), Object(Psalm\Type\Atomic\TNamedObject), false, false, false, true)
#8 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(190): Psalm\Internal\Analyzer\Statements\Expression\Call\StaticCallAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\StaticCall), Object(Psalm\Context))
#9 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(78): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::handleExpression(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\StaticCall), Object(Psalm\Context), false, NULL, false)
#10 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php(60): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\StaticCall), Object(Psalm\Context))
#11 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(186): Psalm\Internal\Analyzer\Statements\Expression\Call\MethodCallAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\MethodCall), Object(Psalm\Context))
#12 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(78): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::handleExpression(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\MethodCall), Object(Psalm\Context), false, NULL, false)
#13 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ReturnAnalyzer.php(156): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\MethodCall), Object(Psalm\Context))
#14 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(546): Psalm\Internal\Analyzer\Statements\ReturnAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\Return_), Object(Psalm\Context))
#15 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(207): Psalm\Internal\Analyzer\StatementsAnalyzer::analyzeStatement(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\Return_), Object(Psalm\Context), NULL)
#16 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/IfAnalyzer.php(68): Psalm\Internal\Analyzer\StatementsAnalyzer->analyze(Array, Object(Psalm\Context))
#17 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/IfElseAnalyzer.php(365): Psalm\Internal\Analyzer\Statements\Block\IfElse\IfAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\If_), Object(Psalm\Internal\Scope\IfScope), Object(Psalm\Internal\Scope\IfConditionalScope), Object(Psalm\Context), Object(Psalm\Context), Object(Psalm\Context), Array)
#18 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(518): Psalm\Internal\Analyzer\Statements\Block\IfElseAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\If_), Object(Psalm\Context))
#19 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(207): Psalm\Internal\Analyzer\StatementsAnalyzer::analyzeStatement(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\If_), Object(Psalm\Context), Object(Psalm\Context))
#20 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php(476): Psalm\Internal\Analyzer\StatementsAnalyzer->analyze(Array, Object(Psalm\Context), Object(Psalm\Context), true)
#21 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ClassAnalyzer.php(1798): Psalm\Internal\Analyzer\FunctionLikeAnalyzer->analyze(Object(Psalm\Context), Object(Psalm\Internal\Provider\NodeDataProvider), Object(Psalm\Context))
#22 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ClassAnalyzer.php(1471): Psalm\Internal\Analyzer\ClassAnalyzer->analyzeClassMethod(Object(PhpParser\Node\Stmt\ClassMethod), Object(Psalm\Storage\ClassLikeStorage), Object(Psalm\Internal\Analyzer\TraitAnalyzer), Object(Psalm\Context), Object(Psalm\Context))
#23 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ClassAnalyzer.php(437): Psalm\Internal\Analyzer\ClassAnalyzer->analyzeTraitUse(Object(Psalm\Aliases), Object(PhpParser\Node\Stmt\TraitUse), Object(Psalm\Internal\Analyzer\ProjectAnalyzer), Object(Psalm\Storage\ClassLikeStorage), Object(Psalm\Context), Object(Psalm\Context), NULL)
#24 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FileAnalyzer.php(229): Psalm\Internal\Analyzer\ClassAnalyzer->analyze(Object(Psalm\Context), Object(Psalm\Context))
#25 /project/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Analyzer.php(362): Psalm\Internal\Analyzer\FileAnalyzer->analyze()
#26 /project/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Analyzer.php(619): Psalm\Internal\Codebase\Analyzer->Psalm\Internal\Codebase\{closure}(2, '/project/app/mo...')
#27 /project/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Analyzer.php(291): Psalm\Internal\Codebase\Analyzer->doAnalysis(Object(Psalm\Internal\Analyzer\ProjectAnalyzer), 1)
#28 /project/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php(691): Psalm\Internal\Codebase\Analyzer->analyzeFiles(Object(Psalm\Internal\Analyzer\ProjectAnalyzer), 1, false, true)
#29 /project/vendor/vimeo/psalm/src/Psalm/Internal/Cli/Psalm.php(373): Psalm\Internal\Analyzer\ProjectAnalyzer->check('/project/app/', false)
#30 /project/vendor/vimeo/psalm/psalm(7): Psalm\Internal\Cli\Psalm::run(Array)
#31 /project/vendor/bin/psalm(120): include('/project/vendor...')
#32 {main}
Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service "locale.plural.formula". in Symfony\Component\DependencyInjection\ContainerBuilder->getDefinition() (line 935 of /project/vendor/symfony/dependency-injection/ContainerBuilder.php).
@mortenson
Copy link
Owner

@FlorentTorregrosa Is the locale module enabled in your psalm config? Ex:

        <pluginClass class="mortenson\PsalmPluginDrupal\Plugin">
            <containerXml>DrupalContainerDump.xml</containerXml>
            <extensions>
              <module name="field" />
              <module name="language" />
              <module name="file" />
              <module name="locale" />
            </extensions>
        </pluginClass>

@FlorentTorregrosa
Copy link
Contributor Author

Thanks @mortenson for the quick feedback.

It was not present. But I still got the error with the module listed.

@FlorentTorregrosa
Copy link
Contributor Author

FlorentTorregrosa commented Jan 6, 2023

I tried to debug in the DrupalKernel to follow the flow of the error stacktrace.

In app/core/lib/Drupal/Core/DrupalKernel.php, I put some debug:

$yaml_loader = new YamlFileLoader($container);
    foreach ($this->serviceYamls['app'] as $filename) {
      if ($filename == 'core/modules/locale/locale.services.yml') {
        $container->has('locale.plural.formula') ? var_dump('yes') : var_dump('no');
      }
      $yaml_loader->load($filename);
      if ($filename == 'core/modules/locale/locale.services.yml') {
        $container->has('locale.plural.formula') ? var_dump('yes') : var_dump('no');
      }
    }

It gave:

Target PHP version: 8.1 (inferred from current PHP version)
Scanning files...
string(2) "no"
string(3) "yes"
Analyzing files...

Exception: Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException You have requested a non-existent service "locale.plural.formula".

So I guess the services definitions are loaded correctly. But lost during analysis.

Also I realized that all the modules enabled in my current instance are loaded, not only the one listed in the psalm config. If I put:

    // Register application services.
    $yaml_loader = new YamlFileLoader($container);
    foreach ($this->serviceYamls['app'] as $filename) {
      var_dump($filename);
      $yaml_loader->load($filename);
    }

I see all the services.yml files of my enabled modules.

When looking at the Drupal psalm plugin I saw:

// Copies Psalm\SymfonyPsalmPlugin\Handler\ContainerHandler to support Drupal::service.

in vendor/mortenson/psalm-plugin-drupal/ContainerHandler.php

So I wonder if this class should not be updated because there are been changes between the 2.x and 4.x version of the Symfony plugin.

@FlorentTorregrosa
Copy link
Contributor Author

FlorentTorregrosa commented Jan 6, 2023

About "Also I realized that all the modules enabled in my current instance are loaded, not only the one listed in the psalm config.". This is because in vendor/mortenson/psalm-plugin-drupal/scripts/PsalmDrupalKernel.php::getPsalmModuleList:

 foreach ($xml->xpath('//pluginClass[@class="mortenson\PsalmPluginDrupal\Plugin"]/extensions/module') as $node) {
          
        }

This xpath expression is not working (at least for me). If I dump the $xml I have my xml file loaded but not getting in the foreach.

Edit:

Found the problem. at the beginning of my psalm.xml I have:

<psalm
  ...
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="https://getpsalm.org/schema/config"
  xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
>

The xpath does not like those 3 lines.

@FlorentTorregrosa
Copy link
Contributor Author

FlorentTorregrosa commented Jan 6, 2023

WTF, and now it is working...

Edit: I mean, without those 3 lines, I do not have the problem of service not found... Checking on somewhere else than my computer.

@FlorentTorregrosa
Copy link
Contributor Author

Checked on some else project. I was those 3 lines...

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

No branches or pull requests

2 participants