Skip to content

Commit d9c43e5

Browse files
committed
Support array growth and assignment
1 parent 6803c77 commit d9c43e5

5 files changed

Lines changed: 1833 additions & 4 deletions

File tree

example.php

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,6 +1581,62 @@ public function methodReturnShapeKeys(): void {
15811581
}
15821582
}
15831583

1584+
// ─── Array Shape Inference from Literal Arrays ─────────────────────────────
1585+
//
1586+
// PHPantomLSP can infer array shapes from literal array construction
1587+
// and incremental key assignments — no @var annotation needed.
1588+
1589+
// Literal array with string keys:
1590+
$config = ['host' => 'localhost', 'port' => 3306, 'ssl' => true, 'author' => new User()];
1591+
$config['']; // Key completion suggests: host, port, ssl, author
1592+
// Details: host: string, port: int, ssl: bool, author: User
1593+
1594+
// Incremental key assignments are merged into the shape:
1595+
$result = ['status' => 'ok'];
1596+
$result['code'] = 200;
1597+
$result['user'] = new User();
1598+
$result['']; // Key completion suggests: status, code, user
1599+
// Details: status: string, code: int, user: User
1600+
1601+
// ─── Literal Array Value Type → Member Access ──────────────────────────────
1602+
//
1603+
// When the value type of an array shape key is a class, member access
1604+
// through `$var['key']->` resolves to that class and offers completions.
1605+
// This works for both inline literal arrays and incremental assignments.
1606+
1607+
$result['user']->getEmail(); // Resolved: User::getEmail()
1608+
$result['user']->getName(); // Resolved: User::getName() (inherited from Model)
1609+
1610+
$services = ['logger' => new User(), 'count' => 42];
1611+
$services['logger']->getEmail(); // Resolved: User::getEmail()
1612+
// $services['count']-> // No member completions — int is scalar
1613+
1614+
// ─── Scope-Aware Annotation Resolution ─────────────────────────────────────
1615+
//
1616+
// Annotations inside class methods do NOT leak to file-scope code.
1617+
// If a class has `@param array{host: string, credentials: User} $config`
1618+
// and file-scope code also uses `$config`, completions at file scope
1619+
// come from the literal assignment, NOT the method parameter.
1620+
//
1621+
// Example: the ArrayShapeDemo::connect() method above has
1622+
// @param array{host: string, port: int, credentials: User} $config
1623+
// but the file-scope $config below gets its own keys from the literal:
1624+
$outerConfig = ['host' => 'localhost', 'port' => 3306, 'ssl' => true];
1625+
$outerConfig['']; // Suggests: host, port, ssl (NOT credentials from the class)
1626+
1627+
// Works with empty initial array too:
1628+
$data = [];
1629+
$data['name'] = 'Alice';
1630+
$data['age'] = 30;
1631+
$data['']; // Key completion suggests: name, age
1632+
1633+
// Old-style array() syntax is also supported:
1634+
$opts = array('driver' => 'mysql', 'charset' => 'utf8');
1635+
$opts['']; // Key completion suggests: driver, charset
1636+
1637+
// Note: @var annotations take priority over literal inference.
1638+
// If both exist, only the annotation keys are offered.
1639+
15841640
/**
15851641
* Top-level array shape usage.
15861642
*

0 commit comments

Comments
 (0)