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

integrating Debug Points model into Pharo #16177

Merged
merged 13 commits into from
Feb 23, 2024
Merged
65 changes: 65 additions & 0 deletions doc/DebugPoints/debug-points.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Debug Points

The debug point system is a model destined to replace the former breakpoint and watchpoint model.

## Types of debug points

**Debug points** are different types of **instrumentation that are used to debug**.
For now, there are two concrete types of debug points: **breakpoints and watchpoints**.

As commonly known, breakpoints halts the program and watchpoints saves a value in its history when they are hit.
Basic debug points can also be used but they do nothing unless we add **behaviors** to them.

## Behaviors of debug points

A debug point can have **different types of behaviors** that will execute before the debug point is actually hit.

Among these behaviors, there are:

- *Once* behavior: the debug point becomes disabled after it is hit
- *Count* behavior: counts the number of times the debug point has been hit
- *Condition* behavior: sets a condition that must evaluate to `true` so that the debug point can actually be hit
- *Chain Link* behavior: combines debug points into a chain. In that case, when a debug point is hit in the chain, it disables itself and enables the next debug point in the chain. In other words, each debug points in the chain is hit only once in a specific order
- *Script* behavior: executes a script each time the debug point is hit
- *Transcript* behavior: logs a string to the Transcript each time the debug point is hit

All these behaviors can be set when creating a breakpoint from the Calypso browser in the method editor:

![Installing a breakpoint with behaviors from the Calypso browser in the method editor](https://github.com/adri09070/pharo/assets/97704417/c2f17276-2a3b-431c-bdec-0784bccaea2a)

To have more flexibility to configure existing debug points or to create different types of debug points, it is possible to use an API on `DebugPoint` objects or via the `DebugPointManager`.

It will be possible to configure debug points via a UI tool, the Debug Point Browser, which will be the object of another PR in NewTools.

## Debug Point Targets

Debug points can be installed on different types of targets:

- an *AST node*, which can be targeted by selecting source code in the Calypso browser:
![Targeting an AST node by selecting source code in the Calypso browser](https://github.com/adri09070/pharo/assets/97704417/c2f17276-2a3b-431c-bdec-0784bccaea2a).
In this case, the debug point is reached when the corresponding code is executed.
*NB: To put basic breakpoints quickly on AST nodes, it is still possible to double-click the left bar in the method editor, just like with the ancient breakpoint system:*
![Activating basic breakpoint by double-clicking the left bar in the method editor](https://github.com/adri09070/pharo/assets/97704417/99c5ad24-8224-4e37-9b4f-697a7092c786)
**API:**
+ `DebugPointManager installNew: aDebugPointClass on: anASTNode`: instanciates a debug point class, configured with no behavior, and installs it on on an AST node
+ `DebugPointManager installNew: aDebugPointClass on: aNode withBehaviors: aListOfBehaviorClasses`: instanciates a debug point class, configured with the list of behavior classes, and installs it on on an AST node
- a *variable*, which can be targeted by selecting a variable in the variable view in the Calypso browser:
![Selecting a variable in the variable view in the Calypso browser, to set a debug point on a variable](https://github.com/adri09070/pharo/assets/97704417/d03143b9-dbdf-4b9b-b10e-a8b604488597)
In this case, the debug point is reached each time the targeted variable is read or/and written, according to the debug point's configuration.
**API:**
+ `DebugPointManager installNew: aDebugPointClass inClass: aClass onVariableAccessNamed: aSlotNameSymbol`: instanciates a debug point class, configured with no behavior, and installs it on the instance variable, whose name is given as argument, in a class hierarchy. The debug point is reached at each reading or writing of this variable.
+ `DebugPointManager installNew: aDebugPointClass inClass: aClass onVariableAccessNamed: aSlotNameSymbol withBehaviors: aListOfBehaviorClasses`: instanciates a debug point class, configured with the list of behavior classes, and installs it on the instance variable whose name is given as argument, in a class hierarchy. The debug point is reached at each reading or writing of this variable.
+ `DebugPointManager installNew: aDebugPointClass inClass: aClass onVariableReadNamed: aSlotNameSymbol`: instanciates a debug point class, configured with no behavior, and installs it on the instance variable whose name is given as argument, in a class hierarchy. The debug point is reached at each reading of this variable.
+ `DebugPointManager installNew: aDebugPointClass inClass: aClass onVariableReadNamed: aSlotNameSymbol withBehaviors: aListOfBehaviorClasses`: instanciates a debug point class, configured with the list of behavior classes, and installs it on the instance variable whose name is given as argument, in a class hierarchy. The debug point is reached at each reading of this variable.
+ `DebugPointManager installNew: aDebugPointClass inClass: aClass onVariableWriteNamed: aSlotNameSymbol`: instanciates a debug point class, configured with no behavior, and installs it on the instance variable whose name is given as argument, in a class hierarchy. The debug point is reached at each writing to this variable.
+ `DebugPointManager installNew: aDebugPointClass inClass: aClass onVariableWriteNamed: aSlotNameSymbol withBehaviors: aListOfBehaviorClasses`: instanciates a debug point class, configured with the list of behavior classes, and installs it on the instance variable whose name is given as argument, in a class hierarchy. The debug point is reached at each writing to this variable.
- an *object*, in order to install object-centric debug points. This type of target **wraps another target** (AST node or variable). In this case, the debug point is reached only if the wrapped target is reached and if the receiver is the target instance.
**API:**
+ `DebugPointManager installNew: aDebugPointClass on: anASTNode forObject: anObject`: instanciates a debug point class, configured with no behavior, and installs it on on an AST node. The debug point is hit only if the receiver is the target object given as argument.
+ `DebugPointManager installNew: aDebugPointClass on: aNode withBehaviors: aListOfBehaviorClasses forObject: anObject`: instanciates a debug point class, configured with the list of behavior classes, and installs it on on an AST node. The debug point is hit only if the receiver is the target object given as argument.
+ `DebugPointManager installNew: aDebugPointClass forObject: anObject onVariableAccessNamed: aSlotNameSymbol`: instanciates a debug point class, configured with no behavior, and installs it on the instance variable, whose name is given as argument, only for the target object given as argument. The debug point is reached at each reading or writing of this variable.
+ `DebugPointManager installNew: aDebugPointClass forObject: anObject onVariableAccessNamed: aSlotNameSymbol withBehaviors: aListOfBehaviorClasses`: instanciates a debug point class, configured with the list of behavior classes, and installs it on the instance variable whose name is given as argument, only for the target object given as argument. The debug point is reached at each reading or writing of this variable.
+ `DebugPointManager installNew: aDebugPointClass forObject: anObject onVariableReadNamed: aSlotNameSymbol`: instanciates a debug point class, configured with no behavior, and installs it on the instance variable whose name is given as argument, only for the target object given as argument. The debug point is reached at each reading of this variable.
+ `DebugPointManager installNew: aDebugPointClass forObject: anObject onVariableReadNamed: aSlotNameSymbol withBehaviors: aListOfBehaviorClasses`: instanciates a debug point class, configured with the list of behavior classes, and installs it on the instance variable whose name is given as argument, only for the target object given as argument. The debug point is reached at each reading of this variable.
+ `DebugPointManager installNew: aDebugPointClass forObject: anObject onVariableWriteNamed: aSlotNameSymbol`: instanciates a debug point class, configured with no behavior, and installs it on the instance variable whose name is given as argument, only for the target object given as argument. The debug point is reached at each writing to this variable.
+ `DebugPointManager installNew: aDebugPointClass forObject: anObject onVariableWriteNamed: aSlotNameSymbol withBehaviors: aListOfBehaviorClasses`: instanciates a debug point class, configured with the list of behavior classes, and installs it on the instance variable whose name is given as argument, only for the target object given as argument. The debug point is reached at each writing to this variable.
1 change: 1 addition & 0 deletions src/BaselineOfBasicTools/BaselineOfBasicTools.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ BaselineOfBasicTools >> baseline: spec [
spec
baseline: 'UI' with: [ spec repository: repository ];
baseline: 'Reflectivity' with: [ spec repository: repository ];
baseline: 'DebugPoints' with: [ spec repository: repository ];
baseline: 'Athens' with: [
spec
loads: 'Cairo-core';
Expand Down
3 changes: 3 additions & 0 deletions src/BaselineOfCalypso/BaselineOfCalypso.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ BaselineOfCalypso >> baseline: spec [
spec requires: #( #'Calypso-SystemPlugins-Reflectivity-Queries'
#'Calypso-SystemTools-FullBrowser'
#'Calypso-SystemTools-QueryBrowser' ) ];
package: #'Calypso-SystemPlugins-DebugPoints-Browser' with: [
spec requires: #( #'Calypso-SystemTools-FullBrowser'
#'Calypso-SystemTools-QueryBrowser' ) ];
package: #'Calypso-SystemPlugins-Reflectivity-Browser-Tests'
with: [
spec requires: #( #'Calypso-SystemPlugins-Reflectivity-Browser' ) ];
Expand Down
30 changes: 30 additions & 0 deletions src/BaselineOfDebugPoints/BaselineOfDebugPoints.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Class {
#name : 'BaselineOfDebugPoints',
#superclass : 'BaselineOf',
#category : 'BaselineOfDebugPoints',
#package : 'BaselineOfDebugPoints'
}

{ #category : 'baselines' }
BaselineOfDebugPoints >> baseline: spec [

<baseline>
spec for: #common do: [
spec
baseline: 'Reflectivity'
with: [ spec repository: (self packageRepositoryURLForSpec: spec) ].

spec
package: 'DebugPoints'
with: [ spec requires: #( 'Reflectivity' ) ].

spec
package: 'DebugPoints-Tests'
with: [ spec requires: #( 'DebugPoints' ) ].

"Groups"
spec
group: 'Core' with: #( 'DebugPoints' );
group: 'Tests' with: #( 'Core' 'DebugPoints-Tests' );
group: 'default' with: #( 'Tests' ) ]
]
1 change: 1 addition & 0 deletions src/BaselineOfDebugPoints/package.st
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Package { #name : 'BaselineOfDebugPoints' }
7 changes: 5 additions & 2 deletions src/BaselineOfIDE/BaselineOfIDE.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ BaselineOfIDE >> baseline: spec [
spec for: #common do: [
spec postLoadDoIt: #postload:package:.
spec baseline: 'BasicTools' with: [ spec repository: repository ].
spec package: 'Tool-MorphicProfiler' with: [ spec requires: #( 'BasicTools' ) ].
spec
package: 'Tool-MorphicProfiler'
with: [ spec requires: #( 'BasicTools' ) ].
spec baseline: 'Athens' with: [ spec repository: repository ].
spec baseline: 'Flashback' with: [ spec repository: repository ].

Expand All @@ -57,6 +59,7 @@ BaselineOfIDE >> baseline: spec [
load: 'SUnit' group: 'Tests' spec: spec;
load: 'EnlumineurFormatter' group: 'Tests' spec: spec;
load: 'Reflectivity' group: 'tests' spec: spec;
load: 'DebugPoints' group: 'Tests' spec: spec;
load: 'Refactoring' group: 'Tests' spec: spec.

spec package: 'Math-Operations-Extensions-Tests'.
Expand Down Expand Up @@ -109,7 +112,7 @@ BaselineOfIDE >> baseline: spec [
with: [ spec repository: repository ].
spec baseline: 'ClassParser' with: [ spec repository: repository ].


self
load: 'Calypso'
group: #( 'FullEnvironment' 'SystemBrowser' 'Tests' )
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"
I define a command to add a breakpoint on the AST node corresponding to the selected code
"
Class {
#name : 'ClyAddBreakPointCommand',
#superclass : 'ClyDebuggingPointsCommand',
#category : 'Calypso-SystemPlugins-DebugPoints-Browser',
#package : 'Calypso-SystemPlugins-DebugPoints-Browser'
}

{ #category : 'testing' }
ClyAddBreakPointCommand class >> canBeExecutedInContext: aBrowserContext [

^ (super canBeExecutedInContext: aBrowserContext)
]

{ #category : 'activation' }
ClyAddBreakPointCommand class >> contextMenuOrder [
^1
]

{ #category : 'activation' }
ClyAddBreakPointCommand class >> methodEditorLeftBarClickActivation [

<classAnnotation>
^ CmdTextLeftBarDoubleClickActivation for: ClyMethodSourceCodeContext
]

{ #category : 'accessing' }
ClyAddBreakPointCommand >> defaultMenuIconName [
^#smallError
]

{ #category : 'accessing' }
ClyAddBreakPointCommand >> defaultMenuItemName [
^' Add Breakpoint to: ', sourceNode displaySourceCode
]

{ #category : 'execution' }
ClyAddBreakPointCommand >> execute [

| dp |
dp := DebugPointManager installNew: BreakDebugPoint on: sourceNode.

self putIconInProperties: dp
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"
I define a command to add a watchpoint on the AST node corresponding to the selected code
"
Class {
#name : 'ClyAddWatchDebugPointCommand',
#superclass : 'ClyDebuggingPointsCommand',
#category : 'Calypso-SystemPlugins-DebugPoints-Browser',
#package : 'Calypso-SystemPlugins-DebugPoints-Browser'
}

{ #category : 'testing' }
ClyAddWatchDebugPointCommand class >> canBeExecutedInContext: aBrowserContext [

^ (super canBeExecutedInContext: aBrowserContext)
]

{ #category : 'activation' }
ClyAddWatchDebugPointCommand class >> contextMenuOrder [
^4
]

{ #category : 'accessing' }
ClyAddWatchDebugPointCommand >> defaultMenuIconName [
^#history
]

{ #category : 'accessing' }
ClyAddWatchDebugPointCommand >> defaultMenuItemName [
^' Add Watch to: ', sourceNode displaySourceCode
]

{ #category : 'execution' }
ClyAddWatchDebugPointCommand >> execute [

| dp |
dp := DebugPointManager installNew: WatchDebugPoint on: sourceNode.
self putIconInProperties: dp
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"
I am a command to install breakpoints on readings of variables.
"
Class {
#name : 'ClyBreakOnVariableReadCommand',
#superclass : 'ClyDebugBreakOnVariableCommand',
#category : 'Calypso-SystemPlugins-DebugPoints-Browser',
#package : 'Calypso-SystemPlugins-DebugPoints-Browser'
}

{ #category : 'accessing' }
ClyBreakOnVariableReadCommand class >> accessStrategy [

^ #read
]

{ #category : 'testing' }
ClyBreakOnVariableReadCommand class >> isAbstract [

^ false
]

{ #category : 'accessing' }
ClyBreakOnVariableReadCommand >> defaultMenuItemName [

^ 'Break on read'
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"
I am a command to install breakpoints on readings and writings of variables.
"
Class {
#name : 'ClyBreakOnVariableReadWriteCommand',
#superclass : 'ClyDebugBreakOnVariableCommand',
#category : 'Calypso-SystemPlugins-DebugPoints-Browser',
#package : 'Calypso-SystemPlugins-DebugPoints-Browser'
}

{ #category : 'accessing' }
ClyBreakOnVariableReadWriteCommand class >> accessStrategy [

^ #all
]

{ #category : 'testing' }
ClyBreakOnVariableReadWriteCommand class >> isAbstract [

^ false
]

{ #category : 'accessing' }
ClyBreakOnVariableReadWriteCommand >> defaultMenuItemName [

^ 'Break on access'
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"
I am a command to install breakpoints on writings of variables.
"
Class {
#name : 'ClyBreakOnVariableWriteCommand',
#superclass : 'ClyDebugBreakOnVariableCommand',
#category : 'Calypso-SystemPlugins-DebugPoints-Browser',
#package : 'Calypso-SystemPlugins-DebugPoints-Browser'
}

{ #category : 'accessing' }
ClyBreakOnVariableWriteCommand class >> accessStrategy [

^ #write
]

{ #category : 'testing' }
ClyBreakOnVariableWriteCommand class >> isAbstract [

^ false
]

{ #category : 'accessing' }
ClyBreakOnVariableWriteCommand >> defaultMenuItemName [

^ 'Break on write'
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"
I am a command to install breakpoints on variables of a class
"
Class {
#name : 'ClyDebugBreakOnVariableCommand',
#superclass : 'ClyDebugVariableCommand',
#category : 'Calypso-SystemPlugins-DebugPoints-Browser',
#package : 'Calypso-SystemPlugins-DebugPoints-Browser'
}

{ #category : 'accessing' }
ClyDebugBreakOnVariableCommand class >> debugPointClass [

^ BreakDebugPoint
]
Loading