@@ -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