Skip to content

Conversation

@kzhrk
Copy link
Contributor

@kzhrk kzhrk commented Nov 13, 2025

Closes #2519

Summary

Extends the vue/no-ref-as-operand rule to detect and report when ref objects
returned from composable functions are used without accessing the .value property.

Previously, the rule only detected direct ref declarations like ref(0).
Now it also detects ref objects returned from composable functions:

// ❌ Before: No warning (bug)
const ok = useOk() // returns Ref<boolean>
const msg = ok ? 'yes' : 'no' // No warning was shown

// ✅ After: Warning shown
const ok = useOk() // returns Ref<boolean>
const msg = ok ? 'yes' : 'no' // Warning: Must use `.value` to read or write the value wrapped by `useOk()`.

Motivation

Composable functions are a common pattern in Vue 3 for code reuse. When they return
Ref objects, developers should use the .value property to access the wrapped value.
However, the rule previously had no way to detect when these composable-returned refs
were used incorrectly.

This enhancement provides early feedback to developers, helping them follow Vue 3
best practices and preventing subtle bugs.

Implementation Details

  • Function body analysis: Uses AST analysis to detect when functions return ref objects
  • Pattern support: Handles multiple return patterns:
    • Direct ref() calls: return ref(0)
    • Object properties: return { data: ref(0) }
    • Array elements: return [ref(0)]
  • All scope contexts: Properly searches all scopes to find function definitions
  • Error messages: Shows composable function names in error messages for clarity

Scope and Limitations

The detection works for composable functions defined in the same file. Due to
ESLint's single-file analysis model, composable functions imported from external
modules cannot be analyzed. This is a fundamental ESLint framework constraint.

Testing

  • Added 6 comprehensive test cases covering:
    • Simple composable functions returning ref
    • Arrow functions returning ref
    • Array destructuring from composable returns
    • Proper .value access detection
    • Error detection when .value is missing
  • All 55 tests pass (49 existing + 6 new)
  • No breaking changes to existing functionality

Implement comprehensive support for detecting ref objects returned from composable functions
in the no-ref-as-operand rule. This enhancement includes:

Type Information Foundation:
- Add utility functions to detect functions that return Ref objects
- checkFunctionReturnsRef(): Analyzes function bodies for ref returns
- isRefCall(): Recursively checks for ref() calls in various patterns
- Support for multiple return patterns:
  * Direct ref() calls: return ref(0)
  * Object properties: return { data: ref(0) }
  * Array elements: return [ref(0)]

Composable Function Detection:
- Implement processComposableRefCall() method for handling composable function calls
- Build map of ref-returning functions via body analysis (not JSDoc)
- Detect variable assignments from composable function calls
- Properly handle all scope contexts, not just global scope
- Generate appropriate error messages showing composable function names

Testing:
- Add 6 new test cases covering composable function ref detection
- Test valid usage with proper .value access
- Test invalid usage without .value access
- All 55 tests pass (49 existing + 6 new)

This approach is more robust than JSDoc detection as it analyzes actual code structure
and works reliably in test environments.
@changeset-bot
Copy link

changeset-bot bot commented Nov 13, 2025

🦋 Changeset detected

Latest commit: 2507cc9

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
eslint-plugin-vue Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@kzhrk kzhrk marked this pull request as ready for review November 16, 2025 10:00
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.

vue/no-ref-as-operand to support ref from composable

1 participant