Skip to content

Conversation

@EladBezalel
Copy link
Collaborator

Summary

Implements deterministic reference tracking for internal (non-exported) symbols, matching TypeScript's findAllReferences behavior. This partially addresses #16 by implementing the "exported container" concept.

Problem

When an internal function changes, domino would only look for direct cross-file references. Since internal functions aren't exported, it would find 0 references and stop, missing the entire dependency chain.

Example scenario:

// Internal function changes
function getHelperValue() { return 'modified'; }  // ← Changed

// Used by exported component
export function ExportedComponent() {
  return getHelperValue();  // ← Uses internal function
}

// Imported elsewhere
import { ExportedComponent } from './module';

Before this fix: Domino stops at getHelperValue, doesn't detect affected consumers
After this fix: Domino finds ExportedComponent uses it, tracks its references

Solution

Implemented two algorithms from TypeScript's findAllReferences:

1. Exported Container Tracking

When an internal symbol has no cross-file references and isn't exported:

  • Find which exported symbols in the same file use it
  • Recursively track references to those exported symbols

2. Dynamic Import File Processing

When a file is conservatively affected (dynamic imports with line=0 sentinel):

  • Process all exports from that file
  • Continue the dependency chain

Changes

src/semantic/analyzer.rs:

  • Added is_symbol_exported() - checks if a symbol is exported
  • Added find_exported_symbols_using() - finds which exported symbols depend on an internal symbol

src/core.rs:

  • Modified process_changed_symbol() to handle internal symbols
  • Added special handling for line=0 sentinel (conservatively affected files)

tests/integration_test.rs:

  • Added test_internal_function_affecting_exported_component()

Testing

✅ Unit tests pass
✅ New integration test added
✅ Verified to match traf's behavior in real-world monorepos

Related to Issue #16

This PR partially addresses #16 by implementing:

  • Exported container concept - Finding which exported symbols contain references to changed internal symbols
  • Infrastructure for write vs read tracking - Identifying container symbols that reference changed symbols
  • Dynamic import edge cases - Conservative processing of exports from dynamically imported files

Remaining items from #16 (for future PRs):

  • Type vs Value distinction (namespace tracking)
  • Shorthand property handling
  • Explicit write vs read access flags
  • Scope-bounded search optimizations

This is a critical correctness fix that ensures domino detects all affected projects when internal implementation details change.

This fix implements deterministic reference tracking for internal (non-exported)
symbols, matching TypeScript's findAllReferences behavior.

Problem:
When an internal function (not exported) changes, domino would only look for
direct cross-file references to it. Since internal functions aren't exported,
it would find 0 references and stop, missing the entire dependency chain.

Example:
- getHelperValue() changes (internal function in Component.tsx)
- getHelperValue is used by ExportedComponent (exported)
- ExportedComponent is used by ComponentAdapter (exported)
- ComponentAdapter is dynamically imported by COMPONENTS_MAP
- COMPONENTS_MAP is used by Container (exported from main index)
- Container is imported by app-client

Without this fix, domino stops at getHelperValue and misses app-client.

Solution:
Implemented two key improvements following TypeScript's findAllReferences algorithm:

1. Exported Container Tracking
   When an internal symbol has no cross-file references and isn't exported:
   - Find which exported symbols in the same file use it
   - Recursively track references to those exported symbols

2. Dynamic Import File Processing
   When a file is marked as conservatively affected (due to dynamic imports we
   can't statically analyze with line=0 sentinel value):
   - Process all exports from that file
   - Continue the dependency chain through those exports

Changes:
- src/semantic/analyzer.rs: Added is_symbol_exported() and
  find_exported_symbols_using() methods to identify which exported symbols
  depend on internal symbols

- src/core.rs: Modified process_changed_symbol() to:
  1. Check if symbol is exported when no cross-file refs found
  2. Find and process exported symbols that use the internal symbol
  3. Handle line=0 sentinel by processing all exports from affected files

- tests/integration_test.rs: Added test_internal_function_affecting_exported_component()
  to verify the fix works correctly

Testing:
Verified to match traf's behavior exactly in real-world monorepo testing.

Related:
Partially addresses #16 (Improve Reference Finding Correctness), specifically:
- Implements the "exported container" concept from TypeScript's findAllReferences
- Provides infrastructure for tracking write vs read access (identifying container symbols)
- Handles dynamic import edge cases with conservative export processing
- Fix clippy warning: use is_some_and instead of map_or
- Optimize find_exported_symbols_using from O(n²) to O(n)
- Add comprehensive comments explaining exported container tracking
- Improve debug logging to distinguish between export cases
- Add pre-commit checklist to CLAUDE.md

Performance improvements:
- Build reference container set once instead of per-export
- Early return when no exports or references found
- More informative debug messages

Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions
Copy link

📦 Preview Release Available

A preview release has been published for commit 12d09d3.

Installation

npm install https://github.com/frontops-dev/domino/releases/download/pr-18-12d09d3/front-ops-domino-0.3.4.tgz

Details

@EladBezalel EladBezalel merged commit d3b7c27 into main Jan 6, 2026
18 checks passed
@EladBezalel EladBezalel deleted the fix/track-exported-containers-for-internal-symbols branch January 6, 2026 08:29
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.

2 participants