Skip to content

fix: correct persistent variable detection with underscores#549

Open
Venshard wants to merge 1 commit into
renpy:masterfrom
Venshard:fix-linter-bug
Open

fix: correct persistent variable detection with underscores#549
Venshard wants to merge 1 commit into
renpy:masterfrom
Venshard:fix-linter-bug

Conversation

@Venshard

@Venshard Venshard commented May 3, 2026

Copy link
Copy Markdown

Summary

Fixes #532

Fixes a bug in the linter where persistent variables containing multiple underscores (e.g., persistent.show_map_debug) are incorrectly flagged as undefined when they appear at the end of a line or before certain non-alphabetic characters.

The Problem

The rxPersistentCheck regex in src/diagnostics.ts uses a trailing anchor [^a-zA-Z] to identify the end of a persistent variable reference.

const rxPersistentCheck = /\s+persistent\.(\w+)[^a-zA-Z]/g;

Because _ (underscore) is a word character (\w) but not an alphabetic character ([a-zA-Z]), the regex engine backtracks when it encounters an underscore it can't skip, or when the variable is at the end of a line.

Reproduction Case

Consider the following line of code:

persistent.show_map_debug = not persistent.show_map_debug
  1. For the first occurrence, the = after the variable satisfies [^a-zA-Z], so it matches show_map_debug correctly.
  2. For the second occurrence (at the end of the line), there is no character after debug.
  3. The regex engine captures show_map_debug in (\w+), but then fails to find [^a-zA-Z].
  4. It backtracks, capturing show_map in (\w+).
  5. It then successfully matches the following _ (from _debug) as the [^a-zA-Z] character.
  6. Result: The linter thinks the code is referencing persistent.show_map, which hasn't been defined, and throws a warning.

The Fix

Updated the regex to use a positive lookahead (?=[^a-zA-Z0-9_]|$). This ensures that the capture group (\w+) only matches the full identifier by asserting that it is followed by either a non-identifier character (like space, colon, or equals) or the end of the line.

The updated regex is:

const rxPersistentCheck = /\s+persistent\.(\w+)(?=[^a-zA-Z0-9_]|$)/g;

This prevents the regex engine from backtracking and matching partial identifiers (like show_map from show_map_debug) just to satisfy the trailing character requirement.

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.

Persistent variable marked as "not defined or defaulted" when it is, and works in game

1 participant