Skip to content

Add feature: Go to definition#402

Draft
QuangNguyenMinh123 wants to merge 4 commits intoepasveer:mainfrom
QuangNguyenMinh123:feature/Go_to_definition
Draft

Add feature: Go to definition#402
QuangNguyenMinh123 wants to merge 4 commits intoepasveer:mainfrom
QuangNguyenMinh123:feature/Go_to_definition

Conversation

@QuangNguyenMinh123
Copy link
Contributor

@QuangNguyenMinh123 QuangNguyenMinh123 commented Dec 15, 2025

This MR adds a “Go to Definition” feature, mimicking VS Code
In which, I will use 2 short cuts: "F12" and "Ctrl + left click"
image

@QuangNguyenMinh123 QuangNguyenMinh123 force-pushed the feature/Go_to_definition branch 2 times, most recently from 0a4d76c to eb6634c Compare December 20, 2025 09:06
@QuangNguyenMinh123 QuangNguyenMinh123 marked this pull request as ready for review December 20, 2025 14:29
@QuangNguyenMinh123
Copy link
Contributor Author

QuangNguyenMinh123 commented Dec 20, 2025

Demo: Click on any function, variable or typedef and press F12
Screencast from 20-12-2025 21:28:42.webm

@QuangNguyenMinh123
Copy link
Contributor Author

Workflow:
When the user presses F12, the SeerEditorWidgetSourceArea reads the selected string.
The SeerEditorWidgetSourceArea passes that string to the EditorManagerWidget, which then forwards it to the GdbWidget.
At this point, we need to perform two tasks:

  1. Synchronize Seer and GDB
    This is necessary because determining the correct identifier requires Seer to perform multiple steps (these steps may not be obvious when debugging desktop applications, but they become critical when using OpenOCD). Since the GDB process and the Seer main window do not run synchronously, we need to use a mutex and condition variable to keep them in sync.

  2. Keep the GUI responsive
    To prevent the GUI from freezing, we must create a separate thread to handle all of this processing.

Screenshot from 2025-12-20 21-48-19

@QuangNguyenMinh123
Copy link
Contributor Author

Here is the code snippet I wrote to implement the 'Go to Definition' feature for OpenOCD
Screenshot from 2025-12-20 21-57-28
Further more, debugOnInit feature will also use thread for synchronization. It is

@QuangNguyenMinh123
Copy link
Contributor Author

Also, I will add to SeerSourceBrowserWidget:
SeerSourceBrowserWidget::findFileWithRegrex and QMap<QString,QString> _sourceFiles
They save list of source code whenever a new gdb session is created
Occasionally, -symbol-info-variables, -symbol-info-functions, and -symbol-info-types return an unrelated source file.
SeerSourceBrowserWidget::findFileWithRegex is invoked to determine whether those files should be ruled out

@epasveer
Copy link
Owner

Quite impressive! Let me go over your details.

@QuangNguyenMinh123
Copy link
Contributor Author

@epasveer What do you think about this MR?

@epasveer
Copy link
Owner

@epasveer What do you think about this MR?

Apologies. I've been busy with the Holidays and New Years. I'll review this MR shortly.

I hope you've had a good Holidays.

@QuangNguyenMinh123
Copy link
Contributor Author

@epasveer What do you think about this MR?

Apologies. I've been busy with the Holidays and New Years. I'll review this MR shortly.

I hope you've had a good Holidays.

My apologies. Christmas isn't typically celebrated in Vietnam, so I assumed you had forgotten about this PR 😂
You don't have to look at this right away; feel free to enjoy the holiday season. Merry Christmas! 🎄

@epasveer
Copy link
Owner

My apologies.

It's all good. I'll be back at things next week 😃

@epasveer
Copy link
Owner

Getting to this now. Sorry for the delay.

@epasveer
Copy link
Owner

Hi @QuangNguyenMinh123

I like adding this feature. My understanding is the "definition" can be a function or it can be a data type. Seer already has this ability via the "Functions" or "Types" tab in the "Source/Symbol" browser in the upper left corner. Your idea makes it much simpler, in a workflow way. Which is always good 😄

I'm a little concerned about introducing a mutex and introducing a work thread. It adds complexity.

What I would have done here is:

  1. When F12 is pressed, SeerSourceEditorAreas::handleGotoDefinition() builds a relevant string from where the cursor is currently at.

  2. Send a signal to SeerEditorManager with that string.

This is basically what you have now in your idea. Below is another idea for the rest.

SeerGdbWidget already has SeerGdbWidget::handleGdbExecutableFunctions and SeerGdbWidget::handleGdbExecutableType

Like SeerTypeBrowserWidget and SeerFunctionBrowserWidget, SeerEditorManager can emit the refreshTypeList(_id, typeSearchLineEdit->text()) and refreshFunctionList(_id, functionSearchLineEdit->text()) signals to SeerGdbWidget and parse the results and open up the file at the proper line.

Note, the text you provide from the cursor position may result in multiple occurrences of symbols or types. Have to decide how to handle this. (Open all, open none, open first). The text may match a function and a type. Again, have to decide how to handle this.

One thing to note, the refreshFunctionList() signal takes a "id". This is a unique id the widget (in this case SeerEditorManager) uses to filter out messages that are meant just for itself and not other widgets. See SeerTypeBrowserWidget as an example. It the constructor, it uses Seer::createID() to create an unique id. And the signal passes it on, then the handleText() function keys on it.

I don't see the need of a mutex, unless I'm missing something. Also, I'm not clear on what you mean by "syncronizing".

Anyway, give my idea some thought.

Oh, in your code there was a table of keywords. What are they for?

Thanks for you great ideas!

@QuangNguyenMinh123
Copy link
Contributor Author

Hi @epasveer
"syncronizing" was probably a typo — I meant synchronizing.
I have removed the mutex and condition variable, and it seems to work well, so I'll keep them removed.
I did notice SeerGdbWidget::handleGdbExecutableFunctions and SeerGdbWidget::handleGdbExecutableType, but since I want something simpler, I created my own function instead.
I'm also concerned about cases where functions, typedefs, and variables have the same name.
So far, everything has been working smoothly. I'll create a test case that uses identical names for a function, a variable, and a typedef to see how it behaves and what can be done.
Best regards

@epasveer
Copy link
Owner

Okay. I'll review it again when you're done.

@QuangNguyenMinh123
Copy link
Contributor Author

@epasveer
After checking gdb mi, it seems that gdb doesn't have any solution for this
Also, I have other work that needs to be done.
I’d like to take a look at the VS Code source code sometime to see how they trace identifiers, but probably not right now.
I’ve already tested this feature together with OpenOCD on my local version, and so far it works reasonably well — mainly because we’ll never use functions, variables, and types with identical names anyway. So I’ll keep this MR open for the future.

@epasveer
Copy link
Owner

After checking gdb mi, it seems that gdb doesn't have any solution for this

Just so we're on the same page, solution for what?

@QuangNguyenMinh123
Copy link
Contributor Author

Just so we're on the same page

For distinguishing between variable, typedef, and function identifiers:
Currently, what I’ve done is to invoke all three commands
-symbol-info-variables, -symbol-info-functions, and -symbol-info-types with the same identifier as the argument.
However, it seems that GDB MI cannot distinguish which one is a variable, function, or typedef.
Eg: If I have both a function void Test() and a struct Test, and I point to Test of void Test and press F12 to go to the definition of Test, GDB doesn’t know exactly whether Test refers to the function, the typedef/struct, or a variable. It just returns all of them. With a little bit of luck, the cursor might point to void Test; otherwise it might point to typedef or variable

@epasveer
Copy link
Owner

However, it seems that GDB MI cannot distinguish

I'm not surprised about this.

With regular gdb, one has to decide to use one of these commands up front. ie: the user knows which one to use.

(gdb) info types ^mytype
(gdb) info functions ^myfunction
(gdb) info variables ^myvariable

I don't think we can read the user's mind to know which one to use.

Perhaps, call each one, and if they result in multiple results, so be it. Open a source viewer for each one. I don't think we can do much else.

@epasveer
Copy link
Owner

Looking at your original image.

image

So this may result with this logic.

Go to Definition may mean -symbol-info-variables
Go to Declaration may mean -symbol-info-functions
Go to Type Definition may mean -symbol-info-types

@QuangNguyenMinh123 QuangNguyenMinh123 marked this pull request as draft January 27, 2026 01:51
@QuangNguyenMinh123
Copy link
Contributor Author

Hi @epasveer , sorry for delay
Since types, variables, and functions rarely have exactly the same name, could we just temporarily ignore this case, mark it as a known issue, and merge this MR anyway?
I use my Seer version with OpenOCD to debug embedded systems at my workplace, and I’ve actually never encountered a case where identifiers had identical names.

@epasveer
Copy link
Owner

could we just temporarily ignore this case, mark it as a known issue, and merge this MR anyway?

Sure. I'll review it again, just to be sure ("main" has other new changes) and will merge it if okay.

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