Nonymous: Function-Object Consumption Naming Algorithm Implementation

Demo/test page for a proposed way of automatically naming anonymous functions for editors, debuggers, and other tools

Naming Algorithm ResultsInput Source

  
  var main = function() {             // 1. main
   var foo = new Foo(
      function(){                     // 2. main/foo<
        this.welcome = "Hi!";
      });
   var bar = new Bar("GoodBye.");
   console.log(foo.welcome);
   console.log(bar.message);
  };
  var Foo = function(){               // 3. Foo<
    var instances;
    return function(initializer){     // 4. Foo
        instances++;
        initializer.apply(this);
      };
  }();
  var Baz = Bar = function(msg){      // 5. Bar
    this.message = msg;
  }

  
  // Case 1: Object Property Initializer

var anObject = {
  aPropertyInitialized: function() {
    return true;
  }
};
function Fuz(){};
Fuz.prototype = {
  add: function(child) {
    this.children.push(child);
  },
}

  
var x = 1;
x = function(){};                                                 // x

x = window.addEventListener("something", {onFoo: function(){}});  // x<onFoo

x = window.addEventListener('load', function(event) {}, false);   // x<(load-fal)

addEventListener('load', function(event) {}, false);  // addEventListener(load-fals);

  
define(["uglify-js", "lib/nonymous/nonymous.js"], function(mUglifyJs, mNonymous) {
});

  
// Some named functions that we should be finding the names of...
function foo() {
  return 1;
}
var bar = function bax() {
  return 2;
}

  
// nested function call with no assignment
function callNoAssign() {
  this.fileClient.fetchChildren(parentItem.ChildrenLocation).then( 
				dojo.hitch(this, function(children) {
					mUtil.processNavigatorParent(parentItem, children);
					onComplete(children);
				})
			);
}

  
// function in argument with another function argument
function otherArgAlsoFunction() {
  this._convertDelimiter(text, function(t) {clipboadText.push(t);}, function() {clipboadText.push(delimiter);});
}

  
  var x = {fox: { bax: function(){} } };	//  fox.bax
  foo.foo.foo = function(){};
  var z = {
    foz: function() {
      var baz = function() {
        var y = {bay: function() {}};  // foz/baz/bay
      };
    }
  };
  var outer = function() {
    x.fox.bax.nx = function(){};
    var w = {fow: { baw: function(){} } };	//  outer/fow.baw
  };

  
function foo() {
  return function bar(){
    return true;
  }
}
orion.textview.TextView = (function() {

	/** @private */
	function addHandler(node, type, handler, capture) {
		if (typeof node.addEventListener === "function") {
			node.addEventListener(type, handler, capture === true);
		} else {
			node.attachEvent("on" + type, handler);
		}
	}
}());

  
// Case 2: Entry in an Array Literal
var fromYUI = {
  _attach:function(el, notifier, delegate) {
    if(Y.DOM.isWindow(el)){
      return Event.attach([type, function(e){
        notifier.fire(e);
      },el]);
    }
  }
};

  
// Case 3: Property assignment with property identifier
  this.eventPool_.createObject = function() {
    return new goog.debug.Trace_.Event_();
  };

  
// Case 4: Property assignment with property name string
  this.eventPool_["createObject"] = function() {
    return new goog.debug.Trace_.Event_();
  };

  
// Case 5: Property Assignment With  Property Name Variable
  jQuery.each("ajaxStart ajaxStop ajaxComplete ajaxError"
    .split(" "), function( i, o ) {
       jQuery.fn[o] = function( f ) {
         return this.bind(o, f);
       };
  });

  
// Case 6:  Property Assignment With  Property Name Expressions
  function define(D) {
    if (!element) element = getRootElement();
    property[D] = 'client' + D;
    viewport['get' + D] = function() { 
      return element[property[D]] 
    };
    return viewport['get' + D]();
  }

  
// Case 7: Assignment to an Element of an Array
var arr = [];
arr[0] = function() { 
  return "I'm nothing"; 
  }

  
// Case 8: Assignment to a Variable
var foo;
foo = function() {
  return 'metasyntactic';
  };

  
// Case 9: Anonymous Functions Immediately Called
  Y.ClassNameManager = function () {
    var sPrefix = CONFIG[CLASS_NAME_PREFIX],
    sDelimiter = CONFIG[CLASS_NAME_DELIMITER];
    return {
      getClassName: Y.cached(function () {
        var args = Y.Array(arguments);
        if (args[args.length-1] !== true) {
          args.unshift(sPrefix);
        } else {
          args.pop();
        }
        return args.join(sDelimiter);
      })
    };
  }();

  
// Case 10: Function Property is Accessed
var fromExtJS = {
  setVisible : function(v, a, d, c, e){
    if(v){
      this.showAction();
    }
    if(a && v){
      var cb = function(){
        this.sync(true);
          if(c){
             c();
          }
      }.createDelegate(this);
    }
    // .....
  }
};

  
// Case 11:  Returned From a Function Call
var fromDojo = {
  registerWin: function(targetWindow, effectiveNode){
    if(doc){
      if(dojo.isIE){
        return function(){
          doc.detachEvent('onmousedown', mousedownListener);
          doc.detachEvent('onactivate', activateListener);
          doc.detachEvent('ondeactivate', deactivateListener);
          doc = null;    
        };
      }else{
        return function(){
          doc.removeEventListener('mousedown', mousedownListener, true);
          doc.removeEventListener('focus', focusListener, true);
          doc.removeEventListener('blur', blurListener, true);
          doc = null;   
        };
      }
    }
  }
}

  
// Case 12: Function Passed as an Argument
  Y.ClassNameManager = function () {
    var sPrefix = CONFIG[CLASS_NAME_PREFIX],
    sDelimiter = CONFIG[CLASS_NAME_DELIMITER];
    return {
      getClassName: Y.cached(function () {
        var args = Y.Array(arguments);
        if (args[args.length-1] !== true) {
          args.unshift(sPrefix);
        } else {
          args.pop();
        }
        return args.join(sDelimiter);
      })
    };
  }();

  
   jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
	    // ...
		function handler( e ) { 
			e = jQuery.event.fix( e );
			e.type = fix;
			return jQuery.event.trigger( e, null, e.target );
		}
	});

  
   var obj = {
     relative: {
        "": function(checkSet, part, isXML){
			var nodeCheck,
				doneName = done++,
				checkFn = dirCheck;

			if ( typeof part === "string" && !/\W/.test(part) ) {
				part = part.toLowerCase();
				nodeCheck = part;
				checkFn = dirNodeCheck;
			}

			checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
		}
	}
   };

  
 var outerObj = {
  _oneItemChanged : function(){
    // ..
    dojo.forEach(nodes, function(node){});
    //...
  }
};

  
  var DOMPLATE = {
    'DIV': function() { return 'div';},
    'IMG': function() { return 'img';},
    };
  with (DOMPLATE) {
    DOMPLATE.Editor = domplate(Firebug.BaseEditor,
    {
      foo: function() {
        return DIV()+IMG();
      }
    });
  }

Try out different naming marker options:
MarkerRole
Name component is a property
Function contributes to the name component
Function's location within an argument summary
Scope separator
Name is enclosed in a property
The max number of characters used in an argument summary