Skip to content

Bug: getFromFunctionParameters() hangs on a multi-line set(...) call with nested calls #149

Description

@vix-4800

Summary

php-namespace-resolver v2.1.3 can make VS Code unresponsive on save/open for a specific PHP code pattern.

The problem is reproducible with a small standalone file and does not require a very large class.

What happens

When the extension processes a file containing a multi-line set(...) call with a nested call in the second argument,
the extension host becomes unresponsive.

In VS Code this looks like:

  • PHP diagnostics stop responding
  • Git decorations freeze
  • file search becomes sluggish or stops working
  • saving the file may hang until the window is reloaded

Disabling MehediDracula.php-namespace-resolver immediately fixes the problem.

In the installed v2.1.3 build, PhpClassDetector.getFromFunctionParameters() uses this regex:

/(?:function\s+\w+|function|fn|set)\s*\(((?:[^()]*|\([^()]*\))*)\)/gm;

The |set alternative means any set(...) call is treated like a function signature candidate. That appears unintended
for a method-call parser and causes catastrophic slowdown for the code pattern below.

Minimal reproduction

This small file is enough to reproduce the problem:

<?php

declare(strict_types=1);

namespace Temp\Repro;

final class NamespaceResolverRegexRepro
{
    private MemoryStore $store;

    private DemoAccount $account;

    public function __construct()
    {
        $this->store = new MemoryStore();
        $this->account = new DemoAccount('demo-42');
    }

    public function warmUpToken(): void
    {
        $size = 12;
        $suffix = 'sync';

        $this->store->set(
            'resolver_probe_' . $this->account->uuid . '_' . $suffix,
            strtoupper(bin2hex(random_bytes($size)))
        );
    }
}

final class MemoryStore
{
    public function set(string $key, string $value): void
    {
    }
}

final class DemoAccount
{
    public function __construct(public string $uuid)
    {
    }
}

If I change only this text:

$this->store->set(

to:

$this->store->put(

without changing the rest of the file, the detector completes in a few milliseconds.

Likewise, on a larger real-world file, replacing the single ->set( occurrence in-memory makes detectAll() finish
immediately.

Reproduction steps

  1. Install MehediDracula.php-namespace-resolver v2.1.3
  2. Open the file above in VS Code
  3. Save the file or let the extension analyze it
  4. VS Code becomes sluggish or unresponsive

Direct detector reproduction

Running the detector directly against the file also hangs:

timeout 8s node <<'NODE'
const fs = require('fs');
const { PhpClassDetector } = require('/path/to/mehedidracula.php-namespace-resolver-2.1.3/out/core/PhpClassDetector.js');
const text = fs.readFileSync('NamespaceResolverRegexRepro.php', 'utf8');
const detector = new PhpClassDetector();
const start = Date.now();
const classes = detector.detectAll(text);
console.log('elapsedMs', Date.now() - start, 'classes', classes.length);
NODE

Expected behavior

The extension should not hang or block the VS Code extension host on ordinary method calls named set(...).

Actual behavior

The detector enters an extremely slow regex path and the extension can freeze VS Code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions