Fix offset issue#466
Open
richardm90 wants to merge 18 commits intocodefori:mainfrom
Open
Conversation
Prevents multiple concurrent parse operations during live editing that were causing duplicate definitions with incorrect offsets, resulting in false linter errors about variable name casing.
Improves the offset issue fix by adding parse ID tracking to invalidate stale parse operations, a parsing flag to prevent concurrent parses, error handling, and reduces debounce time from 500ms to 300ms for better responsiveness. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Removes the `parsing` state flag that was preventing concurrent parses. The new approach allows up to 2 concurrent parses per document, with automatic invalidation of stale results via the parseId mechanism. This fixes the issue where document changes during an active parse would not trigger a new parse, leaving the latest changes unparsed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Adds comprehensive timestamped logging for debugging parse operations: - Parse lifecycle tracking (start, completion, duration, parseId) - Include file fetch operations with timing and cache status - URI validation with timing - File fetch operations with cache hits/misses - Clean filename extraction (strips query parameters) Fixes include fetch deduplication bug where fetchingInProgress flag was cleared too early, before async getFileRequest() completed. This caused duplicate server requests for the same include file during a single parse operation. Now the flag is only cleared after all async work completes, properly preventing duplicate fetches. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
The library list is connection-level, so per-file cache scoping was unnecessary.
Contributor
Author
|
I have added tests for the bits I could but I haven't created tests for the debounce logic nor the race condition. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Problem
I've experienced odd behaviour when changing RPG source in that the linter would suddenly display a "Variable name casing does not match definition" warning at various points within the source I was editing. Although this appears to be a linter issue it goes further, the tokens appear to lose their offset within the source so when you use something like F2 to rename a symbol it loses track of where those symbols are and renames the wrong text in the source.
/includefiles - I do use a lot of/includefiles.I was able to pull together a very simple example that replicates the problem, which I've also created a video that demonstrates the problem as it's not easy to understand from the description.
rm82test-2025-10-30_20.45.00.mp4
Full disclosure I leaned on Claude Code to help fix the problem and produce the documentation of the changes.
The extension was experiencing race condition offset issues that manifested as false linter errors during live editing:
The Solution
The fix implements a comprehensive debouncing and synchronization mechanism with multiple layers of protection:
Debouncing (server.ts)
Parse State Tracking
Parse ID Validation
Concurrent Parse Handling
needsReparse = truerather than starting a second concurrent parseneedsReparseand triggers the queued re-parse automaticallyInclude File Fetch Deduplication (server.ts)
Fixed critical bug where fetchingInProgress flag was cleared too early:
This prevents duplicate server requests for the same include file during a single parse operation.
Changed the include file fetch call to pass
fileUri(the current file being parsed) instead ofworkingUri(the root document). This fixes:Changed
resolvedMembersandresolvedStreamfilesfrom per-document maps ({[baseUri]: {[fileKey]: ...}}) to global flat maps ({[fileKey]: ...}):onDidClosehandler in the linter no longer purges these cachesAdded a new
vscode-rpgle.logLevelsetting with options:none,error,warn,info(default),debug.logWithTimestamp()which respects the configured levelgetDisplayName()strips query parameters and decodes URL encodingAdded comprehensive timestamped logging for debugging:
.catch()block to gracefully handle parse errorsTechnical Flow
parseId→ Invalidate any in-flight parsesneedsReparse = trueand waitparseId→ Only update diagnostics if still latestneedsReparse→ Trigger queued re-parse if neededKey Improvements
Files Changed
extension/server/src/server.ts- Debouncing, parse state tracking, concurrent parse handling, include fetch deduplication, loggingextension/server/src/connection.ts- Logging infrastructure, configurable log level, flattened resolution caches, enhanced logging for URI validation, file fetches, and member/streamfile resolutionextension/server/src/providers/linter/index.ts- Removed per-document cache clearing on close (caches are now global)language/parser.ts- Fixed include file fetch to use current file URI instead of root document URIpackage.json- Addedvscode-rpgle.logLevelconfiguration settingObservations
I noticed the following whilst working on this fix.
/includefiles are loaded a lot, the extension seems to reload the same file many, many times. I connect over VPN for a lot of my clients and loading source can take a while./includefiles, if they've changed./includestoo.RPGLINT.JSONis not cached in TextDocuments collection, causing a server round-trip every time it's needed.Checklist
console.logs I added