@@ -28,6 +28,7 @@ import { createFieldNonEditableText } from '../fields/FieldNonEditableText';
2828import  {  getAllowedTypesForSetCheck ,  getOutputCheck  }  from  './utils/python' ; 
2929import  {  ExtendedPythonGenerator  }  from  '../editor/extended_python_generator' ; 
3030import  {  MRC_STYLE_FUNCTIONS  }  from  '../themes/styles' 
31+ import  {  ClassMethodDefExtraState  }  from  './mrc_class_method_def' 
3132
3233// A block to call a python function. 
3334
@@ -57,7 +58,8 @@ interface CallPythonFunctionMixin extends CallPythonFunctionMixinType {
5758  mrcImportModule : string , 
5859  mrcActualFunctionName : string , 
5960  mrcExportedFunction : boolean , 
60-   maybeRenameProcedure ( this : CallPythonFunctionBlock ,  oldName : string ,  legalName : string ) : void ; 
61+   renameMethod ( this : CallPythonFunctionBlock ,  oldName : string ,  newName : string ) : void ; 
62+   mutateMethod ( this : CallPythonFunctionBlock ,  defBlockExtraState : ClassMethodDefExtraState ) : void ; 
6163} 
6264type  CallPythonFunctionMixinType  =  typeof  CALL_PYTHON_FUNCTION ; 
6365
@@ -219,59 +221,95 @@ const CALL_PYTHON_FUNCTION = {
219221      this . setNextStatement ( true ,  null ) ; 
220222      this . setOutput ( false ) ; 
221223    } 
222-     // Add the dummy input. 
223-     switch  ( this . mrcFunctionKind )  { 
224-       case  FunctionKind . MODULE :
225-         this . appendDummyInput ( ) 
226-             . appendField ( 'call' ) 
227-             . appendField ( createFieldNonEditableText ( '' ) ,  pythonUtils . FIELD_MODULE_OR_CLASS_NAME ) 
228-             . appendField ( '.' ) 
229-             . appendField ( createFieldNonEditableText ( '' ) ,  pythonUtils . FIELD_FUNCTION_NAME ) ; 
230-         break ; 
231-       case  FunctionKind . STATIC :
232-         this . appendDummyInput ( ) 
233-             . appendField ( 'call' ) 
234-             . appendField ( createFieldNonEditableText ( '' ) ,  pythonUtils . FIELD_MODULE_OR_CLASS_NAME ) 
235-             . appendField ( '.' ) 
236-             . appendField ( createFieldNonEditableText ( '' ) ,  pythonUtils . FIELD_FUNCTION_NAME ) ; 
237-         break ; 
238-       case  FunctionKind . CONSTRUCTOR :
239-         this . appendDummyInput ( ) 
240-             . appendField ( 'create' ) 
241-             . appendField ( createFieldNonEditableText ( '' ) ,  pythonUtils . FIELD_MODULE_OR_CLASS_NAME ) ; 
242-         break ; 
243-       case  FunctionKind . INSTANCE :
244-         this . appendDummyInput ( ) 
245-             . appendField ( 'call' ) 
246-             . appendField ( createFieldNonEditableText ( '' ) ,  pythonUtils . FIELD_MODULE_OR_CLASS_NAME ) 
247-             . appendField ( '.' ) 
248-             . appendField ( createFieldNonEditableText ( '' ) ,  pythonUtils . FIELD_FUNCTION_NAME ) ; 
249-         break ; 
250-       case  FunctionKind . INSTANCE_WITHIN :
251-         this . appendDummyInput ( ) 
252-             . appendField ( 'call' ) 
253-             . appendField ( createFieldNonEditableText ( '' ) ,  pythonUtils . FIELD_FUNCTION_NAME ) ; 
254-         break ; 
255-       default :
256-         throw  new  Error ( 'mrcFunctionKind has unexpected value: '  +  mrcFunctionKind ) 
224+ 
225+     if  ( ! this . getInput ( 'TITLE' ) )  { 
226+       // Add the dummy input. 
227+       switch  ( this . mrcFunctionKind )  { 
228+         case  FunctionKind . MODULE :
229+           this . appendDummyInput ( 'TITLE' ) 
230+               . appendField ( 'call' ) 
231+               . appendField ( createFieldNonEditableText ( '' ) ,  pythonUtils . FIELD_MODULE_OR_CLASS_NAME ) 
232+               . appendField ( '.' ) 
233+               . appendField ( createFieldNonEditableText ( '' ) ,  pythonUtils . FIELD_FUNCTION_NAME ) ; 
234+           break ; 
235+         case  FunctionKind . STATIC :
236+           this . appendDummyInput ( 'TITLE' ) 
237+               . appendField ( 'call' ) 
238+               . appendField ( createFieldNonEditableText ( '' ) ,  pythonUtils . FIELD_MODULE_OR_CLASS_NAME ) 
239+               . appendField ( '.' ) 
240+               . appendField ( createFieldNonEditableText ( '' ) ,  pythonUtils . FIELD_FUNCTION_NAME ) ; 
241+           break ; 
242+         case  FunctionKind . CONSTRUCTOR :
243+           this . appendDummyInput ( 'TITLE' ) 
244+               . appendField ( 'create' ) 
245+               . appendField ( createFieldNonEditableText ( '' ) ,  pythonUtils . FIELD_MODULE_OR_CLASS_NAME ) ; 
246+           break ; 
247+         case  FunctionKind . INSTANCE :
248+           this . appendDummyInput ( 'TITLE' ) 
249+               . appendField ( 'call' ) 
250+               . appendField ( createFieldNonEditableText ( '' ) ,  pythonUtils . FIELD_MODULE_OR_CLASS_NAME ) 
251+               . appendField ( '.' ) 
252+               . appendField ( createFieldNonEditableText ( '' ) ,  pythonUtils . FIELD_FUNCTION_NAME ) ; 
253+           break ; 
254+         case  FunctionKind . INSTANCE_WITHIN : { 
255+           const  input  =  this . getInput ( 'TITLE' ) ; 
256+           if  ( ! input )  { 
257+             this . appendDummyInput ( 'TITLE' ) 
258+                 . appendField ( 'call' ) 
259+                 . appendField ( createFieldNonEditableText ( '' ) ,  pythonUtils . FIELD_FUNCTION_NAME ) ; 
260+           } 
261+           break ; 
262+         } 
263+         default :
264+           throw  new  Error ( 'mrcFunctionKind has unexpected value: '  +  mrcFunctionKind ) 
265+       } 
257266    } 
258-     // Add input sockets for the arguments. 
267+ 
268+     // Update input sockets for the arguments. 
259269    for  ( let  i  =  0 ;  i  <  this . mrcArgs . length ;  i ++ )  { 
260-       const  input  =  this . appendValueInput ( 'ARG'  +  i ) 
261-           . setAlign ( Blockly . inputs . Align . RIGHT ) 
262-           . appendField ( this . mrcArgs [ i ] . name ) ; 
270+       const  argName  =  this . mrcArgs [ i ] . name ; 
271+       let  argInput  =  this . getInput ( 'ARG'  +  i ) ; 
272+       const  argField  =  this . getField ( 'ARGNAME'  +  i ) ; 
273+       if  ( argInput  &&  argField )  { 
274+         // Ensure argument name is up to date. No need to fire a change event. 
275+         Blockly . Events . disable ( ) ; 
276+         try  { 
277+           argField . setValue ( argName ) ; 
278+         }  finally  { 
279+           Blockly . Events . enable ( ) ; 
280+         } 
281+       }  else  { 
282+         // Add new input. 
283+         argInput  =  this . appendValueInput ( 'ARG'  +  i ) 
284+             . setAlign ( Blockly . inputs . Align . RIGHT ) 
285+             . appendField ( argName ,  'ARGNAME'  +  i ) ; 
286+       } 
263287      if  ( this . mrcArgs [ i ] . type )  { 
264-         input . setCheck ( getAllowedTypesForSetCheck ( this . mrcArgs [ i ] . type ) ) ; 
288+         argInput . setCheck ( getAllowedTypesForSetCheck ( this . mrcArgs [ i ] . type ) ) ; 
265289      } 
266290    } 
267-   } , 
268-   maybeRenameProcedure : function ( this : CallPythonFunctionBlock ,  oldName : string ,  newName : string ) : void   { 
269-     if  ( this . mrcFunctionKind  ===  FunctionKind . INSTANCE_WITHIN )  { 
270-       if  ( this . getFieldValue ( pythonUtils . FIELD_FUNCTION_NAME )  ==  oldName )  { 
271-         this . setFieldValue ( newName ,  pythonUtils . FIELD_FUNCTION_NAME ) ; 
272-       } 
291+     // Remove deleted inputs. 
292+     for  ( let  i  =  this . mrcArgs . length ;  this . getInput ( 'ARG'  +  i ) ;  i ++ )  { 
293+       this . removeInput ( 'ARG'  +  i ) ; 
273294    } 
274-   } 
295+   } , 
296+   renameMethod : function ( this : CallPythonFunctionBlock ,  newName : string ) : void   { 
297+     this . setFieldValue ( newName ,  pythonUtils . FIELD_FUNCTION_NAME ) ; 
298+   } , 
299+   mutateMethod : function ( 
300+       this : CallPythonFunctionBlock , 
301+       defBlockExtraState : ClassMethodDefExtraState 
302+   ) : void   { 
303+     this . mrcReturnType  =  defBlockExtraState . returnType ; 
304+     this . mrcArgs  =  [ ] ; 
305+     defBlockExtraState . params . forEach ( ( param )  =>  { 
306+       this . mrcArgs . push ( { 
307+         'name' : param . name , 
308+         'type' : param . type , 
309+       } ) ; 
310+     } ) ; 
311+     this . updateBlock_ ( ) ; 
312+   } , 
275313} ; 
276314
277315export  const  setup  =  function ( )  { 
@@ -356,3 +394,50 @@ function generateCodeForArguments(
356394  } 
357395  return  code ; 
358396} 
397+ 
398+ function  getMethodCallers ( workspace : Blockly . Workspace ,  name : string ) : Blockly . Block [ ]  { 
399+   return  workspace . getBlocksByType ( 'mrc_call_python_function' ) . filter ( ( block )  =>  { 
400+     const  callBlock  =  block  as  CallPythonFunctionBlock ; 
401+     return  ( 
402+       callBlock . mrcFunctionKind  ===  FunctionKind . INSTANCE_WITHIN  && 
403+       callBlock . getFieldValue ( pythonUtils . FIELD_FUNCTION_NAME )  ===  name 
404+     ) ; 
405+   } ) ; 
406+ } 
407+ 
408+ export  function  renameMethodCallers ( workspace : Blockly . Workspace ,  oldName : string ,  newName : string ) : void   { 
409+   for  ( const  block  of  getMethodCallers ( workspace ,  oldName ) )  { 
410+     ( block  as  CallPythonFunctionBlock ) . renameMethod ( newName ) ; 
411+   } 
412+ } 
413+ 
414+ export  function  mutateMethodCallers ( 
415+     workspace : Blockly . Workspace ,  methodName : string ,  defBlockExtraState : ClassMethodDefExtraState )  { 
416+   const  oldRecordUndo  =  Blockly . Events . getRecordUndo ( ) ; 
417+ 
418+   for  ( const  block  of  getMethodCallers ( workspace ,  methodName ) )  { 
419+     const  callBlock  =  block  as  CallPythonFunctionBlock ; 
420+     // Get the extra state before changing the call block. 
421+     const  oldExtraState  =  callBlock . saveExtraState ( ) ; 
422+ 
423+     // Apply the changes. 
424+     callBlock . mutateMethod ( defBlockExtraState ) ; 
425+ 
426+     // Get the extra state after changing the call block. 
427+     const  newExtraState  =  callBlock . saveExtraState ( ) ; 
428+     if  ( oldExtraState  !==  newExtraState )  { 
429+       // Fire a change event, but don't record it as an undoable action. 
430+       Blockly . Events . setRecordUndo ( false ) ; 
431+       Blockly . Events . fire ( 
432+         new  ( Blockly . Events . get ( Blockly . Events . BLOCK_CHANGE ) ) ( 
433+           callBlock , 
434+           'mutation' , 
435+           null , 
436+           oldExtraState , 
437+           newExtraState , 
438+         ) , 
439+       ) ; 
440+       Blockly . Events . setRecordUndo ( oldRecordUndo ) ; 
441+     } 
442+   } 
443+ } 
0 commit comments