-
Notifications
You must be signed in to change notification settings - Fork 0
fix: correct Show in Source navigation (#line offset + unquoted filenames) #44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,4 +6,8 @@ server/out/ | |
| .env | ||
| tests/_* | ||
| docs/ | ||
| .vscode/ | ||
| .vscode/ | ||
| .claude/ | ||
| graphify-out/ | ||
| tests/manuals/ | ||
| .vscode/launch.json | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,3 +25,5 @@ package-lock.json | |
| .env | ||
| .env.* | ||
| docs/ | ||
| graphify-out/ | ||
| tests/manuals/ | ||
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| /** | ||
| * Pure helper functions for line directive navigation. | ||
| * No VS Code dependencies — designed for testability and reusability. | ||
| */ | ||
|
|
||
| // ── Detection ───────────────────────────────────────────────────────────────── | ||
|
|
||
| /** Returns true if the file header looks like a Bison or Flex generated C file. */ | ||
| export function isGeneratedFile(text: string): boolean { | ||
| const header = text.slice(0, 600); | ||
| return ( | ||
| header.includes('/* A Bison parser, made by GNU Bison') || | ||
| header.includes('/* Generated by GNU Bison') || | ||
| header.includes('/* Generated by flex') || | ||
| header.includes('/* A lexical scanner generated by flex') | ||
| ); | ||
| } | ||
|
|
||
| // ── Line directive helpers ──────────────────────────────────────────────────── | ||
|
|
||
| export interface LineDirective { | ||
| sourceLine: number; // 1-based line number in the source file | ||
| sourceFile: string; | ||
| directiveLine: number; // 0-based line index in the generated file where directive was found | ||
| } | ||
|
|
||
| /** | ||
| * Scan backwards from cursorLine to find the nearest #line N "file" or #line N file directive. | ||
| * Returns the directive data including the line index where it was found. | ||
| */ | ||
| export function findNearestLineDirective(lines: string[], cursorLine: number): LineDirective | null { | ||
| for (let i = cursorLine; i >= 0; i--) { | ||
| const m = lines[i].match(/^#line\s+(\d+)\s+"?([^"\s]+)"?/); | ||
| if (m) { | ||
| return { | ||
| sourceLine: parseInt(m[1], 10), | ||
| sourceFile: m[2], | ||
| directiveLine: i, | ||
| }; | ||
| } | ||
| } | ||
| return null; | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| /** | ||
| * Tests for lineDirectiveUtils pure helpers. | ||
| * Run: TS_NODE_PROJECT=tsconfig.base.json npx ts-node tests/test-line-directive.ts | ||
| */ | ||
| import { isGeneratedFile, findNearestLineDirective } from '../client/src/lineDirectiveUtils'; | ||
|
|
||
| let passed = 0, failed = 0; | ||
| function assert(cond: boolean, msg: string, extra?: unknown) { | ||
| if (cond) { console.log(` [PASS] ${msg}`); passed++; } | ||
| else { console.error(` [FAIL] ${msg}${extra !== undefined ? ` → ${JSON.stringify(extra)}` : ''}`); failed++; } | ||
| } | ||
|
|
||
| // ── isGeneratedFile ──────────────────────────────────────────────────────────── | ||
| console.log('\nisGeneratedFile'); | ||
|
|
||
| assert( | ||
| isGeneratedFile('/* A Bison parser, made by GNU Bison 3.8.2. */\n...rest...'), | ||
| 'detects Bison generated file (made by)' | ||
| ); | ||
| assert( | ||
| isGeneratedFile('/* Generated by GNU Bison 3.8 */\n...rest...'), | ||
| 'detects Bison generated file (generated by)' | ||
| ); | ||
| assert( | ||
| isGeneratedFile('/* Generated by flex 2.6.4 */\n...rest...'), | ||
| 'detects Flex generated file (generated by flex)' | ||
| ); | ||
| assert( | ||
| isGeneratedFile('/* A lexical scanner generated by flex */\n'), | ||
| 'detects Flex generated file (lexical scanner)' | ||
| ); | ||
| assert( | ||
| !isGeneratedFile('// My hand-written parser\n'), | ||
| 'rejects non-generated file' | ||
| ); | ||
| assert( | ||
| !isGeneratedFile(''), | ||
| 'rejects empty file' | ||
| ); | ||
|
|
||
| // ── findNearestLineDirective ─────────────────────────────────────────────────── | ||
| console.log('\nfindNearestLineDirective — quoted filenames'); | ||
|
|
||
| { | ||
| // Cursor ON the directive line → offset = 0 | ||
| const lines = ['#line 28 "parser.y"', 'some_func();']; | ||
| const d = findNearestLineDirective(lines, 0); | ||
| assert(d !== null, 'quoted: finds directive on cursor line'); | ||
| if (d) { | ||
| assert(d.sourceLine === 28, 'quoted: sourceLine = 28', d.sourceLine); | ||
| assert(d.sourceFile === 'parser.y', 'quoted: sourceFile = parser.y', d.sourceFile); | ||
| assert(d.directiveLine === 0, 'quoted: directiveLine = 0', d.directiveLine); | ||
| } | ||
| } | ||
|
|
||
| { | ||
| // Cursor 4 lines below the directive → offset = 4 | ||
| // The caller should compute: targetLine = sourceLine - 1 + (cursorLine - directiveLine) = 27 + 4 = 31 | ||
| const lines = [ | ||
| '#line 28 "parser.y"', | ||
| '#include "config.h"', | ||
| '#include <stdlib.h>', | ||
| '#include <string.h>', | ||
| 'void some_func(int mode) {', | ||
| ]; | ||
| const d = findNearestLineDirective(lines, 4); | ||
| assert(d !== null, 'quoted: finds directive 4 lines above cursor'); | ||
| if (d) { | ||
| assert(d.sourceLine === 28, 'quoted: sourceLine = 28', d.sourceLine); | ||
| assert(d.sourceFile === 'parser.y', 'quoted: sourceFile (cursor 4 lines below)', d.sourceFile); | ||
| assert(d.directiveLine === 0, 'quoted: directiveLine = 0', d.directiveLine); | ||
| } | ||
| } | ||
|
|
||
| console.log('\nfindNearestLineDirective — unquoted filenames'); | ||
|
|
||
| { | ||
| // GitMensch case: no quotes | ||
| const lines = ['#line 28 parser.y', 'some_func();']; | ||
| const d = findNearestLineDirective(lines, 1); | ||
| assert(d !== null, 'unquoted: finds directive'); | ||
| if (d) { | ||
| assert(d.sourceLine === 28, 'unquoted: sourceLine = 28', d.sourceLine); | ||
| assert(d.sourceFile === 'parser.y', 'unquoted: sourceFile = parser.y', d.sourceFile); | ||
| assert(d.directiveLine === 0, 'unquoted: directiveLine = 0', d.directiveLine); | ||
| } | ||
| } | ||
|
|
||
| { | ||
| // Unquoted relative path | ||
| const lines = ['#line 5 src/parser.y', 'x = 1;']; | ||
| const d = findNearestLineDirective(lines, 1); | ||
| assert(d !== null, 'unquoted path: finds directive'); | ||
| if (d) { | ||
| assert(d.sourceFile === 'src/parser.y', 'unquoted path: sourceFile', d.sourceFile); | ||
| } | ||
| } | ||
|
|
||
| console.log('\nfindNearestLineDirective — edge cases'); | ||
|
|
||
| { | ||
| // No directive anywhere → null | ||
| const lines = ['int x = 0;', 'return x;']; | ||
| const d = findNearestLineDirective(lines, 1); | ||
| assert(d === null, 'returns null when no directive exists'); | ||
| } | ||
|
|
||
| { | ||
| // Multiple directives — picks the nearest one above cursor | ||
| const lines = [ | ||
| '#line 10 "a.y"', | ||
| 'foo();', | ||
| '#line 20 "b.y"', | ||
| 'bar();', | ||
| ]; | ||
| const d = findNearestLineDirective(lines, 3); | ||
| assert(d !== null, 'picks nearest directive above cursor'); | ||
| if (d) { | ||
| assert(d.sourceLine === 20, 'picks nearest directive above cursor (line)', d.sourceLine); | ||
| assert(d.sourceFile === 'b.y', 'picks nearest directive above cursor (file)', d.sourceFile); | ||
| assert(d.directiveLine === 2, 'directiveLine of nearest directive', d.directiveLine); | ||
| } | ||
| } | ||
|
|
||
| { | ||
| // Cursor on line 0 with no directive → null | ||
| const lines = ['int x = 0;']; | ||
| const d = findNearestLineDirective(lines, 0); | ||
| assert(d === null, 'no directive on line 0 → null'); | ||
| } | ||
|
|
||
| console.log(`\nResults: ${passed} passed, ${failed} failed`); | ||
| if (failed > 0) process.exit(1); |
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that correct? I think yes, but the later use of the offset should possibly have another
+ 1:goes to
note that
#line 6287 "../../cobc/parser.y"says that the next line is line 6287;cursor line (6290) - directive line (6287) = 3 (+1 --> 4 if considered from the #line itself), but the position is only 3 lines below the #line .
Apart from that the feature works fine.