Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ ships, remove every row that names it.
| DR22 | [Complete permissions built in code](todo/drupal.md#dr22-complete-permissions-built-in-code) | Low-Medium | Medium |
| DR23 | [Warn on unknown permission names](todo/drupal.md#dr23-warn-on-unknown-permission-names) | Medium | Low-Medium |
| DR24 | [Warn on unknown theme hook names](todo/drupal.md#dr24-warn-on-unknown-theme-hook-names) | Low-Medium | Medium-High |
| DR25 | [Warn on unknown plugin IDs](todo/drupal.md#dr25-warn-on-unknown-plugin-ids) | Medium | Low-Medium |
| DR26 | [Annotation class names](todo/drupal.md#dr26-annotation-class-names) | Low-Medium | Low-Medium |

## Yii

Expand Down
34 changes: 34 additions & 0 deletions docs/todo/bugs.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,40 @@ resolves, and so does every name once the whole project is indexed (as
the imports from `import_block_at`, and how a file loaded on demand
records its `use` map in its `FileState`.

### B707. A docblock annotation does not name its class

**Impact: Medium · Complexity: Low-Medium**

```php
use Doctrine\ORM\Mapping as ORM; // Unused import 'Doctrine\ORM\Mapping'
use Symfony\Component\Routing\Annotation\Route; // Unused import

/** @ORM\Entity */
final class User
{
/** @Route("/users") */
public function list(): Response { … }
}
```

Doctrine-style annotations (Doctrine ORM, older Symfony, JMS, Drupal
plugins) name a class with their tag, resolved through the file's `use`
imports like any other class name. The tag is read as an unknown docblock
tag instead, so an import only an annotation uses is reported as unused,
and the quick fix and `phpantom_lsp fix` remove it, which breaks the
annotation at run time. Go-to-definition, hover, references and rename
miss the class too.

Record an annotation tag (`@` then a name, at the start of a docblock
line or inside another annotation's arguments) as a class reference when
its name resolves to a class, the way a docblock type is. A tag PHPDoc
or a tool defines (`@param`, `@phpstan-*`, `@psalm-*`) is never one, and
a lowercase tag with no class behind it stays silent.

**Where to look:** `extract_docblock_symbols` (`src/symbol_map/docblock.rs`),
which emits the class references `unused_imports.rs` and the navigation
features read.

## Code actions

No outstanding items.
Expand Down
46 changes: 46 additions & 0 deletions docs/todo/drupal.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,3 +354,49 @@ implementation cannot be read, would silence every site. Report a name
only once those hooks are read, or with a rule that knows which names
such an implementation can add. A suggestion such as
`acme_greeting__compact` is valid when its base hook is.

---

## DR25. Warn on unknown plugin IDs

**Impact: Medium · Complexity: Low-Medium**

```php
$fields['total'] = BaseFieldDefinition::create('decimel');
$block = $this->blockManager->createInstance('acme_order_sumary');
```

A plugin ID that no plugin of its type declares is a typo or a module the
site lacks. The plugin manager throws for it, except for widgets and
formatters, which silently fall back to the field type's default. Report
one wherever [DR10](#dr10-plugin-ids) reads plugin IDs: field types,
widgets and formatters, constraints, and a plugin manager's
`createInstance()`. A derivative ID (`system_menu_block:main`) is known
only at run time, so an ID whose base plugin has a deriver must not
warn. This depends on DR10.

---

## DR26. Annotation class names

**Impact: Low-Medium · Complexity: Low-Medium**

```php
/**
* @Block(
* id = "acme_order_summary",
* admin_label = @Translation("Order summary"),
* )
*/
final class OrderSummaryBlock extends BlockBase { … }
```

Plugins written before Drupal 10.2 declare themselves in a docblock
annotation, and many contributed modules still do. `@Block` and
`@Translation` name annotation classes, but Drupal's annotated plugin
discovery finds them without a `use` import: it reads a plugin type's
annotation class and namespaces from its plugin manager, not from the
file. Once [B707](bugs.md#b707-a-docblock-annotation-does-not-name-its-class)
reads annotations through the imports, resolve a name the imports don't
cover through the namespaces of the plugin type the class is discovered
for, so that go-to-definition, hover, and references reach the class.
Loading