Skip to content

Highlight visibility method arguments and stop highlighting shadowing locals - #13

Open
tarebyte wants to merge 1 commit into
masterfrom
fix/highlight-visibility-locals
Open

Highlight visibility method arguments and stop highlighting shadowing locals#13
tarebyte wants to merge 1 commit into
masterfrom
fix/highlight-visibility-locals

Conversation

@tarebyte

Copy link
Copy Markdown
Owner

Problem

Follow-up to #8. That PR moved private, protected and public off @keyword, but it only covers the bare form. Two cases on master are still wrong.

A local variable that shadows one of the names is highlighted as a method call. These names can be shadowed, which was part of #8's own argument for not treating them as keywords:

private = 1
private     # highlighted as function.method.builtin, but it is a local read

This was already wrong before #8 — it rendered as keyword — so #8 changed which wrong capture it gets rather than fixing it.

The argument forms do not get the built-in capture at all. private :foo and private def bar; end parse as a call, which the general (call method: (identifier) @function.method) pattern claims. Later patterns win, so the identifier pattern added in #8 never applies to them:

expected highlight 'function.method.builtin', actual highlights: 'function.method'

That leaves private and private :foo rendering differently from each other.

Change

  • Adds #is-not? local to the identifier pattern. The query file already uses exactly this guard on the general @function.method identifier pattern a few lines above, so this follows the existing convention rather than introducing one.
  • Adds a call pattern after the general call pattern, which is where the require pattern already sits for the same precedence reason. !receiver keeps an unrelated method that happens to share a name, such as acl.public, an ordinary call.

Validation

332 corpus parses and 5 highlight files, zero failures. test/highlight/classes.rb goes from 14 to 19 assertions:

Source Capture
private (bare) function.method.builtin
private :with_symbol function.method.builtin
private def with_def; end function.method.builtin
private = 1 then a bare private variable
acl.public function.method

Each new assertion was confirmed to fail without its pattern. Removing #is-not? local gives expected highlight 'variable', actual highlights: 'function.method.builtin'; removing the call pattern gives expected highlight 'function.method.builtin', actual highlights: 'function.method'.

Follow-up to #8, which changed `private`, `protected` and `public` from
`@keyword` to `@function.method.builtin` but only for the bare form.

A bare `private` parses as an identifier, but `private :foo` and
`private def bar; end` parse as calls and are claimed by the general call
pattern, so they kept the ordinary `@function.method` capture. Add a call
pattern after that one, using `!receiver` so an unrelated method with a
colliding name stays an ordinary call.

Guard the identifier pattern with `#is-not? local`, matching the general
identifier pattern above it, so a local variable shadowing one of these
names is highlighted as a variable rather than as a method call. That
case was already wrong before #8, as a keyword.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ac21705f-befb-4606-9c83-657e3e9ea0dc
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.

1 participant