@@ -35,6 +35,7 @@ import * as toolboxItems from '../toolbox/items';
3535import { getClassData } from './utils/python' ;
3636import { FunctionData } from './utils/python_json_types' ;
3737import { findConnectedBlocksOfType } from './utils/find_connected_blocks' ;
38+ import { makeLegalName } from './utils/validator' ;
3839import { NONCOPYABLE_BLOCK } from './noncopyable_block' ;
3940import { BLOCK_NAME as MRC_GET_PARAMETER_BLOCK_NAME } from './mrc_get_parameter' ;
4041import * as paramContainer from './mrc_param_container'
@@ -285,10 +286,23 @@ const CLASS_METHOD_DEF = {
285286 // When the user changes the method name on the block, clear the mrcPythonMethodName field.
286287 this . mrcPythonMethodName = '' ;
287288
288- // Strip leading and trailing whitespace.
289- name = name . trim ( ) ;
289+ if ( this . isInFlyout ) {
290+ // Flyouts can have multiple methods with identical names.
291+ return name ;
292+ }
293+
294+ const otherNames : string [ ] = [ ] ;
295+ this . workspace . getBlocksByType ( BLOCK_NAME )
296+ . filter ( block => block . id !== this . id )
297+ . forEach ( ( block ) => {
298+ otherNames . push ( block . getFieldValue ( FIELD_METHOD_NAME ) ) ;
299+ const classMethodDefBlock = block as ClassMethodDefBlock ;
300+ if ( classMethodDefBlock . mrcPythonMethodName ) {
301+ otherNames . push ( classMethodDefBlock . mrcPythonMethodName ) ;
302+ }
303+ } ) ;
290304
291- const legalName = findLegalMethodName ( name , this ) ;
305+ const legalName = makeLegalName ( name , otherNames , /* mustBeginWithLetter */ true ) ;
292306 const oldName = nameField . getValue ( ) ;
293307 if ( oldName && oldName !== name && oldName !== legalName ) {
294308 // Rename any callers.
@@ -366,61 +380,6 @@ const CLASS_METHOD_DEF = {
366380 } ,
367381} ;
368382
369- /**
370- * Ensure two identically-named methods don't exist.
371- * Take the proposed method name, and return a legal name i.e. one that
372- * is not empty and doesn't collide with other methods.
373- *
374- * @param name Proposed method name.
375- * @param block Block to disambiguate.
376- * @returns Non-colliding name.
377- */
378- function findLegalMethodName ( name : string , block : ClassMethodDefBlock ) : string {
379- if ( block . isInFlyout ) {
380- // Flyouts can have multiple methods called 'my_method'.
381- return name ;
382- }
383- name = name || 'unnamed' ;
384- while ( isMethodNameUsed ( name , block . workspace , block ) ) {
385- // Collision with another method.
386- const r = name . match ( / ^ ( .* ?) ( \d + ) $ / ) ;
387- if ( ! r ) {
388- name += '2' ;
389- } else {
390- name = r [ 1 ] + ( parseInt ( r [ 2 ] ) + 1 ) ;
391- }
392- }
393- return name ;
394- }
395-
396- /**
397- * Return if the given name is already a method name.
398- *
399- * @param name The questionable name.
400- * @param workspace The workspace to scan for collisions.
401- * @param opt_exclude Optional block to exclude from comparisons (one doesn't
402- * want to collide with oneself).
403- * @returns True if the name is used, otherwise return false.
404- */
405- function isMethodNameUsed (
406- name : string , workspace : Blockly . Workspace , opt_exclude ?: Blockly . Block ) : boolean {
407- const nameLowerCase = name . toLowerCase ( ) ;
408- for ( const block of workspace . getBlocksByType ( BLOCK_NAME ) ) {
409- if ( block === opt_exclude ) {
410- continue ;
411- }
412- if ( nameLowerCase === block . getFieldValue ( FIELD_METHOD_NAME ) . toLowerCase ( ) ) {
413- return true ;
414- }
415- const classMethodDefBlock = block as ClassMethodDefBlock ;
416- if ( classMethodDefBlock . mrcPythonMethodName &&
417- nameLowerCase === classMethodDefBlock . mrcPythonMethodName . toLowerCase ( ) ) {
418- return true ;
419- }
420- }
421- return false ;
422- }
423-
424383export const setup = function ( ) {
425384 Blockly . Blocks [ BLOCK_NAME ] = CLASS_METHOD_DEF ;
426385} ;
0 commit comments