Hi, Some code is very “active”, executed all the time, e.g. collections, graphics… or imagine if you work on the compiler or debugger.
It would really be nice if we could test a change before accepting it. Something like “Accept for Test” where magically the original method does not change, yet, when running tests, the version of the code we accepted for testing is executed. So how do we implement that? 1) menu in the browser. I did a quick hack, a Suggestions AST menu shows for all nodes (to be replaced with the “correct” way later). SugsSuggestion subclass: #SugsAcceptForTest instanceVariableNames: '' classVariableNames: '' package: 'SmartSuggestions-Suggestion’ label ^'Accept for test’ So, now we can do everything in the #execute method. What do we need? 1) How we know that we are in a test? —> CurrentExecutionEnvironment value isTest 2) can we compile the buffer even if there are syntax errors (kind of what I expect to happen in non-accepted code)? —> yes, remember, we use the same Parser for syntax highlighting and we extended code-generation for SyntaxError Nodes in the past (it raises a syntax error at runtime, isn’t that kind off odd in a fun way?). newMethod := context selectedClass compiler source: context code; options: #(+ optionParseErrors); compile. 3) Now how to we “hook into” the execution of the original unchanged method? We use a MetaLink. We install it as a before link on the RBMethodNode, the meta-object is a block. This block gets as arguments the thisContext and the arguments of the original method and then just does what you want it do do: if we are in test, return the result of the execution of the method we just compiled. (Closures are fun, we can just reference the outer temp newMethod, no need to store it anywhere else explicitly): [ :aContext :args | CurrentExecutionEnvironment value isTest ifTrue: [ aContext return: (newMethod valueWithReceiver: aContext receiver arguments: args) ] ]; Thus, all the code is this: execute | newMethod metaLink | “we compile a new method from the not-accepted text editor. Allow syntax errors" newMethod := context selectedClass compiler source: context code; options: #(+ optionParseErrors); compile. "the link executes the method we just created and returns" metaLink := MetaLink new metaObject: [ :aContext :args | CurrentExecutionEnvironment value isTest ifTrue: [ aContext return: (newMethod valueWithReceiver: aContext receiver arguments: args) ] ]; selector: #value:value:; arguments: #(context arguments). context selectedMethod ast link: metaLink Cleanup we do not care as everything will be GCed as soon as we accept the method for real. And it works! I did not test it too much, but it seems to do what it is supposed to do. (but more tests and testing are for sure needed) https://github.com/pharo-project/pharo/pull/1182 Next step: move it to a better place in the menu. Marcus