Skip to content
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

PHP: New way to set the current breakpoint #6891

Merged
merged 1 commit into from
Dec 30, 2023

Conversation

troizet
Copy link
Collaborator

@troizet troizet commented Dec 28, 2023

Now the logic of determining the current breakpoint is based on the information received from xdebug's response to the stack_get command, which is not always used to correctly determine the current breakpoint.

Since version 3.1.0 xdebug provides possibility to get information about current breakpoint.
To do this you need to enable breakpoint_details feature.
https://bugs.xdebug.org/bug_view_page.php?bug_id=00001969

In this PR I implemented the use of this feature, with fallback to the old logic, in case xdebug does not support this feature.

Examples before and after (using xdebug version 3.1.6):

  • Write code:
<?php

echo 'Hi!';

function x()
{
    echo 'Hello';
    return 12;
}

$x = x();
  • Set two method breakpoints on the x() function: one with stop on call, the other with stop on return

behavior before:

current_function_breakpoint_before.mp4

behavior after:

current_function_breakpoint_after.mp4
  • Write code:
<?php

echo 'Hi!';

class MethodBreakpoint
{
    public function x()
    {
            echo 'Hello';
            return 12;
    }
}

$cls = new MethodBreakpoint();

$x = $cls->x();
  • Set two method breakpoints on the x() method: one with stop on call, the other with stop on return

behavior before:

current_method_breakpoint_before.mp4

behavior after:

current_method_breakpoint_after.mp4
  • Write code:
<?php

echo 'Hi!';

$foo = $bar['foo'];
  • Set exception breakpoint on Notice

behavior before:

current_exception_breakpoint_before.mp4

behavior after:

current_exception_breakpoint_after.mp4
  • Write code:
<?php

echo 'Hi';

$s = 12;

echo 'Hello';
  • Put two breakpoints on the line echo 'Hello'; with different conditions (the order in which the breakpoints are set is important!):
    • first $s == 4
    • then $s == 12

behavior before:

current_line_breakpoint_before.mp4

behavior after:

current_line_breakpoint_after.mp4

@troizet troizet added the PHP [ci] enable extra PHP tests (php/php.editor) label Dec 28, 2023
@troizet troizet requested review from tmysik and junichi11 December 28, 2023 08:14
Copy link
Member

@tmysik tmysik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, see my comment, thank you.

CC @junichi11

@@ -54,6 +54,7 @@ public class BreakpointModel extends ViewModelSupport implements NodeModel {
private static final String EXCEPTION = "TXT_Exception"; // NOI18N
private static final String PARENS = "()"; // NOI18N
private final Map<DebugSession, AbstractBreakpoint> myCurrentBreakpoints;
private Boolean searchCurrentBreakpointById = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent threading - you are writing it under lock but read it without it. I guess that simple volatile should be fine in this case, so without any further locking.

}
}

public Boolean isSearchCurrentBreakpointById() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public Boolean isSearchCurrentBreakpointById() {
@CheckForNull
public Boolean isSearchCurrentBreakpointById() {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, do we need to allow null for this field? I mean, cannot it be simply a boolean?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I get it right, I would simply define it as boolean with default value false; and, if this feature is enabled/supported, it would be set to true. So, no need for null.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with Tomas. If we use Boolean, we have to check null every time. It seems that null is not set. So, we can use boolean, I think (if I didn't overlook anything).

DebugSession.IDESessionBridge bridge = session.getBridge();
if (bridge != null) {
BreakpointModel breakpointModel = bridge.getBreakpointModel();
if (breakpointModel != null && breakpointModel.isSearchCurrentBreakpointById()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I am not wrong, breakpointModel.isSearchCurrentBreakpointById() can produce a NPE, right?

@@ -96,7 +96,7 @@ private void updateBreakpointsView(DebugSession session, List<Stack> stacks) {
IDESessionBridge bridge = session.getBridge();
if (bridge != null) {
BreakpointModel breakpointModel = bridge.getBreakpointModel();
if (breakpointModel != null) {
if (breakpointModel != null && !breakpointModel.isSearchCurrentBreakpointById()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I am not wrong, breakpointModel.isSearchCurrentBreakpointById() can produce a NPE, right?

String feature = ((FeatureSetCommand) command).getFeature();
if (feature.equals(FeatureGetCommand.Feature.BREAKPOINT_DETAILS.toString())) {
Node error = getChild(getNode(), ERROR);
if (error != null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: this whole condition can be perhaps a bit simplified:

setSearchCurrentBreakpointById(session, error == null);

@tmysik
Copy link
Member

tmysik commented Dec 28, 2023

Thanks a lot for this PR! However, my knowledge of PHP DBG module is very limited, so I hope that @junichi11 will be able to review the change itself properly 😅

@junichi11
Copy link
Member

@troizet Thank you for your work and great description :) I agree with Tomas. So, could you have a look at the review?

@junichi11 junichi11 added this to the NB21 milestone Dec 28, 2023
@troizet troizet force-pushed the php_improve_set_current_breakpoint branch from a38e13e to 5110799 Compare December 28, 2023 17:19
@troizet
Copy link
Collaborator Author

troizet commented Dec 28, 2023

Thank you so much for the review! I have made the suggested changes.

@troizet troizet force-pushed the php_improve_set_current_breakpoint branch from 5110799 to b006691 Compare December 30, 2023 03:47
Copy link
Member

@tmysik tmysik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me now, thanks a lot! 👍

Copy link
Member

@junichi11 junichi11 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. Thank you for your work!

@junichi11
Copy link
Member

Thank you, guys! Merging.

@junichi11 junichi11 merged commit a34e570 into apache:master Dec 30, 2023
@troizet
Copy link
Collaborator Author

troizet commented Dec 30, 2023

@tmysik, @junichi11 Thank you! Happy New Year!

@tmysik
Copy link
Member

tmysik commented Dec 30, 2023

@troizet @junichi11

Happy New Year to you too!

@junichi11
Copy link
Member

@troizet @tmysik Happy New Year to you too!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PHP [ci] enable extra PHP tests (php/php.editor)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants