Skip to content

Drupal permission and configuration names - #540

Merged
AJenbo merged 7 commits into
PHPantom-dev:mainfrom
giuseppe-esposito-87:drupal-dr8
Nov 6, 2026
Merged

AJenbo merged 7 commits into
PHPantom-dev:mainfrom
giuseppe-esposito-87:drupal-dr8

Conversation

@giuseppe-esposito-87

Copy link
Copy Markdown
Contributor

🤖 This was written by an AI agent on behalf of @giuseppe-esposito-87 (claude-code/claude-opus-5-5).

Adds DR8: Drupal permission names and configuration names complete, go to their declaration and show details, and a configuration object's keys complete from its schema.

  • Permissions. Names from every *.permissions.yml complete, go to their declaration, and show their title and description on hover. This works in access checks (hasPermission(), AccessResult::allowedIfHasPermission(s)(), role grants), in each part of a route's _permission (a+b, a,b), and in an entity type's admin_permission.
  • Configuration names. Names from default configuration (config/install, config/optional) and from the schema complete, and go to both the shipped file and the schema entry. This works in \Drupal::config(), the config factory, config() in controllers and forms, getEditableConfigNames(), and #config_target.
  • Configuration keys. get() completes the keys the schema declares, one level at a time, and goes to their schema line. set() and clear() do the same on an editable object only. Keys follow the object through variables and chains, because the configuration name travels in its type (ImmutableConfig<'acme.settings'>, shown on hover).
  • Chained calls on a union. A chained call keeps the type arguments of each member of a union return type. A config form's config() returns Config|ImmutableConfig and needs this, and a chained load() on an entity type ID declared twice now resolves too.

Permissions built by permission callbacks (create article content) are not read. They are filed as DR22, and a warning for unknown permission names as DR23, which depends on DR22.

How to test: run composer install in examples/drupal, then open examples/drupal with this branch's build. In web/modules/custom/acme/:

  • src/NoteAccess.php: hover 'administer acme' to see its title and description. Empty the string and complete: acme's and core's permissions are offered.
  • acme.routing.yml: go to the definition of either half of 'view acme notes+administer acme'.
  • src/Form/SettingsForm.php: go to the definition of 'acme.settings' to reach config/install/acme.settings.yml and config/schema/acme.schema.yml. Empty get('notifications.email') and complete to get notify_email and notifications. Type notifications. to get email.

Checklist

If applicable:

  • I have updated CHANGELOG.md
  • I have updated the documentation (README.md, docs/, examples/)
  • I have updated the config schema (config-schema.json). Not applicable: this PR adds or changes no setting.
  • I have added/updated tests to cover my changes
  • If I used AI tools, I have reviewed what they produced and can explain
    the changes and why they are needed.
  • I have read through any AI-generated text, especially documentation,
    the changelog, and other user-facing content, and removed or corrected
    anything inaccurate, unclear, or unnecessary.

@codecov-commenter

codecov-commenter commented Nov 6, 2026 •

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 96.56471% with 73 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/drupal/config_keys.rs 89.30% 23 Missing ⚠️
src/drupal/config.rs 97.60% 10 Missing ⚠️
src/symbol_map/extraction/drupal.rs 98.44% 9 Missing ⚠️
src/drupal/types.rs 89.33% 8 Missing ⚠️
src/completion/drupal_config.rs 96.13% 7 Missing ⚠️
src/drupal/permissions.rs 96.63% 7 Missing ⚠️
src/completion/drupal_permissions.rs 98.21% 2 Missing ⚠️
src/completion/laravel_string_keys/mod.rs 50.00% 2 Missing ⚠️
src/completion/symfony_string_keys.rs 95.65% 2 Missing ⚠️
src/hover/laravel.rs 50.00% 2 Missing ⚠️
... and 1 more

📢 Thoughts on this report? Let us know!

giuseppe-esposito-87 and others added 7 commits November 6, 2026 17:40
Permission names complete, go to the permissions file that declares
them, and show their title and description on hover, wherever a site
reads one: access checks on accounts and roles, the access result
helpers, the user module's role functions, a route's `_permission`
requirement, and an entity type's `admin_permission`.

Assisted-by: claude-code/claude-opus-5-5
Configuration names complete and go to the default configuration that
ships them and the schema entry that describes them, wherever a site
reads one: `\Drupal::config()`, the config factory, the `config()`
shortcut of controllers and forms, a config form's editable names, and a
form element's `#config_target`.

Assisted-by: claude-code/claude-opus-5-5
A chained call whose return type is a union of generic types keeps each
member's type arguments on its class, as a single generic return type
already does. An entity type ID two classes declare with their own
storage now loads either entity when the load is chained straight on
`getStorage()`.

Assisted-by: claude-code/claude-opus-5-5
A configuration object read by its name carries the name in its type,
and its `get()`, `set()` and `clear()` complete the keys its schema
declares, one level at a time, and go to their schema line. `set()` and
`clear()` offer keys only on an editable object. The key after the `:`
of a `#config_target` and a `ConfigTarget`'s property path do the same.

Assisted-by: claude-code/claude-opus-5-5
Assisted-by: claude-code/claude-opus-5-5
Drupal rejects a configuration name that has no `.`, so a call whose
literal argument has none cannot read a configuration object. Checking
that first spares the config factory and trait subtype walks on the
far more common entity `->get('field_name')` calls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@AJenbo
AJenbo merged commit 8b5d927 into PHPantom-dev:main Nov 6, 2026
12 of 15 checks passed
@AJenbo

AJenbo commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Thanks. You might want to take a look at this:

While a config/schema/*.schema.yml buffer is open and being edited, every keystroke drops the config index, and the next request re-reads every schema file (core has around a hundred) from disk.

@giuseppe-esposito-87

Copy link
Copy Markdown
Contributor Author

🤖 This was written by an AI agent on behalf of @giuseppe-esposito-87 (claude-code/claude-opus-5-5).

Thanks, good catch. #543 keeps each schema file as it was last read and reads only the edited file again, then rebuilds the index in memory. Opening, saving or closing a schema file without changes costs nothing.

@giuseppe-esposito-87
giuseppe-esposito-87 deleted the drupal-dr8 branch November 6, 2026 20:44
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

Successfully merging this pull request may close these issues.

3 participants