Adding function information to the /render page#134
Conversation
There was a problem hiding this comment.
Hi Alon,
Thanks for your contribution!
I went over it, and there are a few things that need more work.
There's a bit of code to change and move around, and tests that need to be written.
Additionally, I think there are visual-design changes required:
- The current color is shared for both the dark and light themes, and only kinda works with either. I think it is better to use different colors for the different themes. This is especially important on the light theme, that currently has very low contrast of text and background.
- As this is a programming tool, and we're presenting data, I think a monospaced font will be a better fit.
- There is currently a lot of spacing in the display. Between the lines and between the labels and the info. I think it should be tightened.
- I think the text should be selectable. There is no reason to prevent selection.
- I think it'll be better for the data to be presented under the controls and not on the opposite side
- Maybe it's worth it to add the project and filepath as well as the function name?
If you have any disagreement regarding the visual side - please let me know!
Last but not least - please make sure you run the linters (bun lint) and they pass before submitting your code. Note that this is critical, and in most cases I would not review code that does not pass the automated checks.
|
Hey Tamir! First of all, thank you for reviewing the code! Regarding linting: Secondly, in Regarding the visual aspects - any preferences you have will be applied Of course, all your comments will be addressed, fixed, and modified accordingly. Thanks again for the review! changes are on the way :) |
The linters passing for all files are required for merging the code, you can see the failing checks at https://github.com/tmr232/function-graph-overview/actions/runs/13949594615/job/39061318568?pr=134
That's my bad - I changed the command from |
extracted the functions and changed app.svelte still working on fetching once in render func.
…pport for additional node types checked with github urls
# Conflicts: # src/control-flow/function-utils.ts
Started testing function name extraction on C++ code. Found multiple issues that need fixing -this part seems to be the hardest so far. BUT hey, we're passing linter... :)
| * @param tag - The capture tag name to filter by. | ||
| * | ||
| */ | ||
| export function extractTaggedValueFromTreeSitterQuery( |
There was a problem hiding this comment.
This functionality is replicating the functionality of the block-matcher.ts file.
Unless you have a good reason not to use it - I'd prefer to used the existing code to maintain consistency.
There was a problem hiding this comment.
Hi, so I'm trying to replace this function and I wanted to ask a few questions.
In the file block-matcher.ts, the function matchQuery returns only the first match.
That works pretty well for me, except for a couple of small cases.
In my function I'm using captures, which give me all the captures from all matches.
This is sometimes useful, for example when there are multiple assignments to multiple functions.
For instance, in Go:
var x, y = func() {}, func() {}Maybe I should add a capture function to block-matcher.ts and export it?
I'd really like to hear a suggestion.
Just shooting an idea:
what if matchQuery would return all the matches,
but in the class the function match still return just the first one?
Then I could also add a function called matchAll that returns all the matches.
There was a problem hiding this comment.
I did this in another branch earlier, it helps me a bit.
Do you want me to keep it, or better not change this file?
Link to diffs (only block-matcher.ts)
| test("arrow variations", () => { | ||
| const code1 = "<T,>(value: T): T[] => {};"; | ||
| expect(namesFrom(code1)).toEqual(["<anonymous>"]); | ||
|
|
||
| const code2 = ` | ||
| function f() { | ||
| const b = n => n + 1; | ||
| const c = async () => { return 1; }; | ||
| const d = () => () => {}; | ||
| } | ||
| `; | ||
| expect(namesFrom(code2)).toEqual(["f", "b", "c", "d", "<anonymous>"]); |
| test("function expression variants", () => { | ||
| const code1 = "const myFunction = function(name: string): string {};"; | ||
| expect(namesFrom(code1)).toEqual(["myFunction"]); | ||
|
|
||
| const code2 = "const sum = function add(): number {};"; | ||
| expect(namesFrom(code2)).toEqual(["add"]); | ||
|
|
||
| const code3 = "function(name: string): string {};"; | ||
| expect(namesFrom(code3)).toEqual(["<anonymous>"]); | ||
| }); |
There was a problem hiding this comment.
These checks repeat the same pattern. Please make them into a parameterized test instead.
Repeats.
There was a problem hiding this comment.
No problem, will do
…changes need to be done.
need to refactor tests and remove dups in all tests.
…g fully - need to refactor all the tests - need to refactor query-utils.ts to use block-matcher.ts
…ph-overview into issue#94 # Conflicts: # src/test/extractNamePython.test.ts
tmr232
left a comment
There was a problem hiding this comment.
Looks good!
Still a few changes needed, but they are minor.
| describe("Go: keyed elements - not supported", () => { | ||
| test("simple keys", () => { | ||
| const code = ` | ||
| var _ = map[interface{}]func(){ | ||
| "simple": func() {}, | ||
| 'r': func() {}, | ||
| fmt.Sprint(1): func() {}, | ||
| T(1): func() {}, | ||
| [2]int{1,2}: func() {}, | ||
| 1 + 2: func() {}, | ||
| } | ||
| `; | ||
| expect(namesFrom(code)).toEqual([ | ||
| undefined, | ||
| undefined, | ||
| undefined, | ||
| undefined, | ||
| undefined, | ||
| undefined, | ||
| ]); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
I'm sorry, but this doesn't really make sense to me. Feels really far fetched.
| /** | ||
| * Extracts the text content of syntax tree nodes captured by a Tree-sitter query. | ||
| * | ||
| * @param func - The syntax node from which to extract the tree. |
| * | ||
| * @param func - The syntax node from which to extract the tree. | ||
| * @param query - The Tree-sitter query string to execute. | ||
| * @param tag - The capture tag name to filter by. |
There was a problem hiding this comment.
Rename to captureName to be consistent with tree-sitter terminology.
| * Mapping of languages to their function name extraction functions. | ||
| * This ensures all supported languages have extractors via TypeScript typing. | ||
| */ | ||
| const functionNameExtractors: Record< |
There was a problem hiding this comment.
Let's move these into the language definition in each cfg-<language>.ts file, and then grab it from the mapping in cfg.ts instead of creating an extra one.
| @@ -106,8 +157,10 @@ async function getFunctionByLine( | |||
| function setBackgroundColor(colors: "light" | "dark") { | |||
There was a problem hiding this comment.
Probably better to rename to applyColors or similar, now that we're not only setting the background color!
|
|
||
| if (params.type === "GitHub") { | ||
| codeUrl = params.codeUrl; | ||
| const { func, language } = await fetchFunctionAndLanguage(params); |
There was a problem hiding this comment.
I don't like that we're fetchign this twice, but I guess we'll have to do for now...
| {#if functionAndCFGMetadata} | ||
| <!-- Metadata display --> | ||
| {#if metadataFields.some(field => showMetadata[field.key] && field.value() !== undefined)} | ||
| <div class="metadata" class:panel-open={isPanelOpen}> | ||
| {#each metadataFields.filter(field => field.value() !== undefined) as { key, label , value}} | ||
| {#if showMetadata[key]} | ||
| <span>{label}: {value()}</span> | ||
| {/if} | ||
| {/each} | ||
| </div> | ||
| {/if} | ||
| <button class="panel-toggle" onclick={togglePanel}> | ||
| {isPanelOpen ? '→' : '←'} | ||
| </button> | ||
| <!-- Control panel --> | ||
| <div class="control-panel" class:open={isPanelOpen}> | ||
| <h3>Display Options</h3> | ||
| {#each metadataFields.filter(field => field.value() !== undefined) as { key, label }} | ||
| <label> | ||
| <input type="checkbox" bind:checked={showMetadata[key]} /> | ||
| {label} | ||
| </label> | ||
| {/each} | ||
| </div> | ||
| {/if} |
| // Update CFG metadata | ||
| const nodeCount: number = CFG.graph.order; | ||
| const edgeCount: number = CFG.graph.size; | ||
| const cyclomaticComplexity: number = CFG.graph.size - nodeCount + 2; // (https://en.wikipedia.org/wiki/Cyclomatic_complexity) |
There was a problem hiding this comment.
Move the comment to above the line, no need for the line to be this long...
| const cyclomaticComplexity: number = CFG.graph.size - nodeCount + 2; // (https://en.wikipedia.org/wiki/Cyclomatic_complexity) | ||
|
|
||
| return { | ||
| functionData: name && lineCount ? { name, lineCount, language } : undefined, |
There was a problem hiding this comment.
Please make this a proper if, or at least use parenthesis around the condition. Readability counts!
removed an unused case in findVariableBinding for TypeScript
Hopefully I did it right, and buherator doesn't count as a surname :-)
|
Thank you Tamir! |


Hey Tamir!
We've added function info to the render page - it updates only when fetching from GitHub (via URL).
Currently, most of the code is in App.svelte.
Here are some example links to test locally (port 5173):
1
2
3
4
5
6
7
8
We are waiting for your feedback and hopefully it meets your standards.