Giter Site home page Giter Site logo

ng-annotate's People

Contributors

andrey-skl avatar anotherchrisberry avatar craigburke avatar duncanbeevers avatar fmmfonseca avatar fracz avatar frapontillo avatar guria avatar mastilver avatar olov avatar pgilad avatar rmariuzzo avatar rubensayshi avatar sdorra avatar siebertm avatar smrq avatar treymack avatar tyson-benson avatar xdissent avatar xierenyuan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ng-annotate's Issues

Incorrect transformation of invoke

It looks like DI variables in invoice methods aren't getting transformed correctly.

The following

var app = angular.bootstrap(document.getElementById('app'), ['app'])
app.invoke(function(Foo) {})

Has no transformation. It should look like this:

var app = angular.bootstrap(document.getElementById('app'), ['app'])
app.invoke([ 'Foo', function(Foo) {} ])

missing annotation via @ngInject when used in js module pattern

controller is annotated correctly but the directive which is exported from the module is not.

there should be debug.ebDebugTool.$inject = ['$window'] after annotation, but none is present.

code before ng-annotate

var app;
(function (app) {
    (function (debug) {
        'use strict';

        var Ctrl = (function () {
            /**
            * @ngInject
            */
            function Ctrl($scope, $element, $attrs) {
                this.$scope = $scope;
                this.$element = $element;
                this.$attrs = $attrs;
            }           
            return Ctrl;
        })();

        /**
        * @ngdoc directive
        * @module lbbw.debug
        * @name  ebDebugTool
        * @restrict E
        *
        * @description
        *
        * @usage
        * ```html
        * <!-- using element directive -->
        * <eb-debug-tool></eb-debug-tool>
        * ```
        *
        * @ngInject
        */
        debug.ebDebugTool = function ($window) {
            var linkFn = function (scope, element, attrs) {
                console.log($window);
            };

            return {
                restrict: 'E',
                templateUrl: '_debug/debugTool.html',
                controller: Ctrl,
                controllerAs: 'ctrl',
                link: linkFn
            };
        };
    })(app.debug || (app.debug = {}));
    var debug = app.debug;
})(app || (app= {}));

after ng-annotate:

var app;
(function (app) {
    (function (debug) {
        'use strict';

        var Ctrl = (function () {
            /**
            * @ngInject
            */
            function Ctrl($scope, $element, $attrs) {
                this.$scope = $scope;
                this.$element = $element;
                this.$attrs = $attrs;
            }
            Ctrl.$inject = ['$scope','$element','$attrs'];           
            return Ctrl;
        })();

        /**
        * @ngdoc directive
        * @module lbbw.debug
        * @name  ebDebugTool
        * @restrict E
        *
        * @description
        *
        * @usage
        * ```html
        * <!-- using element directive -->
        * <eb-debug-tool></eb-debug-tool>
        * ```
        *
        * @ngInject
        */
        debug.ebDebugTool = function ($window) {
            var linkFn = function (scope, element, attrs) {
                console.log($window);
            };

            return {
                restrict: 'E',
                templateUrl: '_debug/debugTool.html',
                controller: Ctrl,
                controllerAs: 'ctrl',
                link: linkFn
            };
        };
    })(app.debug || (app.debug = {}));
    var debug = app.debug;
})(app || (app= {}));

Way to change a service name/reference

Is there a way to change a given service name/reference through the examined source? Since AngularJS doesn't support namespacing when injecting instances and functions, I need to pre-process some libraries that conflict with each other.

Can plugins be used to achieve this?

Support for http interceptors

Http interceptors are not annotated :-)

angular.module('myMod', [])

  .config(function ($httpProvider) {

    var interceptor = function ($rootScope, otherService) {
      return {
        'request': function (config) {
          otherService.doSomething();
          return config || $q.when(config);
        }
      };
    };
    $httpProvider.interceptors.push(interceptor);    
  });

It should output :

...
    var interceptor = ['$rootScope', 'otherService', function ($rootScope, otherService) {
      return {
        'request': function (config) {
          otherService.doSomething();
          return config || $q.when(config);
        }
      };
    }];
    $httpProvider.interceptors.push(interceptor);    
  });

Support variables in directive names

Would it be possible to support the following scenario?

angular.forEach([
    "click",
    "dblclick",
    "mousedown",
    "mouseup",
    "mouseover",
    "mouseout",
    "mousemove",
    "mouseenter",
    "mouseleave",
    "keydown",
    "keyup",
    "keypress",
    "submit",
    "focus",
    "blur",
    "copy",
    "cut",
    "paste"
], function (directiveName) {
    angular.module("directives").directive(directiveName, function ($rootScope) {
        //...
    });
});

Currently, it appears that only a string may be specified as the first parameter to directive in order for ng-annotate to annotate it.

Haven't found a workaround for this one so far.

Adding @ngInject where ng-annotate already matches should not create duplicate injection arrays

Consider the following (which is real world production code):

var optionsView = function (route) {
    return {
        template: "<options items='items' on-select='go(item)' chevrons='true'></options>",
        //Annotated
        controller: function ($scope, $state, navigation) {
        }
    };
};

var rootViews = {
    "mainContainer_root.newsFeed.list": {
        templateUrl: "newsFeed/newsFeed.html",
        //Not annotated
        controller: function ($scope, navigation) {
        }
    },
    "mainContainer_root.settings": optionsView("root.settings")
};

$stateProvider
    .state("root", {
        abstract: true,
        url: "",
        views: rootViews
    });

As you can see, only the first controller: function () gets annotated. The other one doesn't because I'm using a variable instead of directly using $stateProvider (this is fine, I don't think ng-annotate should deal with variables).

However, this poses a problem because I need to /*@ngInject */ only the second controller: function (); if I also /*@ngInject */ the first one, it gets annotated twice. I don't want developers to be thinking whether they should include /*@ngInject */ in their code, so I run grunt-text-replace before grunt-ng-annotate to pre-process some files. With this particular example I have to distinguish between both kind of controller: function () uses to only /*@ngInject */ the second one.

Looking at ng-annotate-main.js I found this:

function matchDirectiveReturnObject(node) {
    // TODO make these more strict by checking that we're inside an angular module?

    // return { .. controller: function($scope, $timeout), ...}

    return node.type === "ReturnStatement" &&
        node.argument && node.argument.type === "ObjectExpression" &&
        matchProp("controller", node.argument.properties);
}

If that check were made, the first controller: function () wouldn't be annotated and I could just /*@ngInject */ every use of it in the file.

Or maybe /*@ngInject */ should only work on pieces of code which haven't already been annotated (which would also allow me to /*@ngInject */ every controller: function ()).

Thanks!

Support for ui-router's controllerProvider

I got a problem when using ng-annotate with the ui-router's controllerProvider in view (have not tested elsewhere). I think it would be useful to implement it in order to fully support ui-router.

Specific code:

        .state('location.detail', {
            url: "/{detailId:[0-9]+}/{type:location|device}_detail",
            views: {
                'content@': {
                    templateUrl: function ($stateParams) {
                        return 'location/location_detail_' + $stateParams.type + '.tpl.html';
                    },
                    controllerProvider: /* @ngInject */ function ($stateParams) {
                        return $stateParams.type.charAt(0).toUpperCase() + $stateParams.type.slice(1) + 'DetailCtrl';
                    }
                }
            }

Thanks!

Can't install from Repo

Don't know if this is relevant: $ npm install -g ng-annotate works fine, but npm install -g git://github.com/olov/ng-annotate.git#48e7fcb throws an error:

npm ERR! Error: ENOENT, chmod '/usr/local/lib/node_modules/ng-annotate/build/es5/ng-annotate'

The only difference I can see is npm WARN excluding symbolic link build/defs-config.json -> ../defs-config.json if I install 48e7fcb.
(I used 48e7fcb as it was the commit to the latest published version. The error occurs with other commit hashes, too. Maybe this is a minor problem, but it is problematic if you want to test bleeding edge versions.)

Make it works with Browserify module structure

Hi,
firstly, thanks for this awesome tool ! :D
I'm trying to integrate Browserify in my development workflow. It works very well.
Now it's the time to automate some tasks with gulp and ng-annotate, and I have an issue with the minification task.
I structure my code exactly the same way from here : http://benclinkinbeard.com/talks/2014/ng-conf/ (slides 19 to 23)

The problem is that ng-annotate isn't working with this kind of structure, something like this isn't parsed properly :

// modules/app/frontend/login/login-index.js
'use strict';

module.exports = function($scope) {
        $scope.name = 'guest';
    };

The previous controller is called from here :

// modules/app/frontend/login/index.js
'use strict';

module.exports = angular.module('app.frontend.login', [])
    .config(function($stateProvider) {
        $stateProvider.state('login', {
            url: '/login',
            templateUrl: '/frontend/login/login-index.html',
            controller: 'LoginCtrl'
        });
    })
    .controller('LoginCtrl', require('./login-index'));

Is there a solution to make ng-annotate understands this kind of line ?

.controller('LoginCtrl', require('./login-index'));

Maybe I'm making something wrong. ^^'

Support explicit @ngNoInject annotation for suppressing false positives

This is great, glad to see such an improvement over ngmin.

One idea I had, which would pretty much allow user-level fixing of any false positives, would be to have a /* @ngNoInject */ annotation, which would disable automatic injection pretty much in the exact situations @ngInject works.

To be clear: I am not having any issue, and this should be a very low priority enhancement, but it might be a nice feature.

doh

close this ... human error

A way to support non-literal service/directive names

I've got a case where I create multiple directives as a combination of 2 parameters:

    ['foo', 'bar'].forEach(function (param1) {
        ['aaa', 'bbb'].forEach(function (param2) {
            angular.module('utils')
                .directive(param1 + param2, function ($timeout) {
                    return {
                        link: function () {},
                    };
                });
        });
    });

This won't get annotated directly because of https://github.com/olov/ng-annotate/blob/master/ng-annotate-main.js#L221 which states only a node of type Literal is considered a name and classifies the 2nd argument to get annotated.
BinaryExpression (or even Identifier) are not enough.

Off course using:

angular.module('utils').directive(param1 + param2, /*@ngInject*/ function ($timeout) {});

does the job, but I wonder if there is any way this could be omitted?
The only thing that comes to my mind is something like:

angular.module('utils').directive((param1 + param2).toString(),  function ($timeout) {});

which makes the first argument possible to distinguish as a string by catching Identifier with name of toString.

I know .toString() is not quite obvious and popular (primarily because it's not necessary when there are 2 strings concatenated to get a string) so I'm not convinced it's the best way such case can be covered.
Do you find it a good enough solution for a PR or should I stay with /*@ngInject*/.
Or maybe you could think of some other way to support dynamic service names?

injector().invoke does not match

The following does not match:

angular
    .injector(['fooModule'])
    .invoke(function (barServiceInFooModule) {
    });

I know it shouldn't be used that much and can be considered a bad practice, but it sometimes can be useful when used with care.
My use case is:
I have to define some callbacks, which will be called much later in config phase.

Annotation resulting in Javascript errors

I have a pretty straight-forward file but the annotations result in Javascript errors.

My test case looks like the following:

angular.module( 'resolveApplicationRoute', [] ).provider( 'resolveApplicationRoute', function resolveApplicationRoute() {

  this.configRouteResolve = function() {
    return promiseRailsAuth
  }

  this.$get = promiseRailsAuth

  // @ngInject
  function promiseRailsAuth( $location, $q, Apis, Omniture, Router, Server, View ) {
    console.log( $location, $q, Apis, Omniture, Router, Server, View )
  }
} )

I compile this locally and get the following output:

angular.module( 'resolveApplicationRoute', [] ).provider( 'resolveApplicationRoute', function resolveApplicationRoute() {

  this.configRouteResolve = function() {
    return promiseRailsAuth
  }

  this.$get = promiseRailsAuth

  // @ngInject
  function promiseRailsAuth( $location, $q, Apis, Omniture, Router, Server, View ) {
    console.log( $location, $q, Apis, Omniture, Router, Server, View )
  }
  promiseRailsAuth.$inject = ["$location", "$q", "Apis", "Omniture", "Router", "Server", "View"];
} )
;

This results in these console errors, which breaks the application:
Console Errors

We never use the .$inject pattern in our un-annotated codebase, not sure what the best way to handle that is.

Injection annotations using wrong $inject syntax

Either I am going mad, or the fn.$injects[...] syntax generated by ng-annotate is actually supposed to be fn.$inject[...].

See: https://docs.angularjs.org/guide/di

So, when annotating something of the form...

/*@ngInject*/
function mainCtrl($scope) {
...
}

...ng-annotate generates...

/*@ngInject*/
function mainCtrl($scope) {
...
}
mainCtrl.$injects["$scope"];

...instead of

/*@ngInject*/
function mainCtrl($scope) {
...
}
mainCtrl.$inject["$scope"];

Can ng-annotate handle methods and variables attached to the $scope

This is not an issue but just a question, I apologize in advanced if I have overlooked this, such as already in the documentation or reported another 'issue', as I haven't been able to locate anything yet.

Would this library be able to turn the code below into the following output. Basically I'm looking for a tool to assist in preparing my $scope methods and variables before minification with Closure Compiler. Currently I run CC in simple mode but I am looking to run it in advanced mode, which to be expected everything attached to $scope is renamed resulting in a completely broken application. I would like to find a tool that can change everything on $scope from dot notation to bracket notation.

Before ng-annotate:

var ngApp = angular.module('ngApp', []);

ngApp.controller('AController', function($scope) {
    $scope.varOne = 'Test';
    $scope.methodOne = function() {
    };
});

After ng-annotate:

var ngApp = angular.module('ngApp', []);

ngApp.controller('AController', ["$scope", function($scope) {
    $scope["varOne"] = "Test";
    $scope["methodOne"] = function() {
    };
}]);

So far all that I can find regarding AngularJS and minification seems to only speak about DI management, I've yet to see how to handle methods and variables that are tied to the actual HTML view via the $scope.

New line issues while testing

I've got a testing issue: some lines are added as \n by ngAnnotate, while others as \r\n. Testing always fails on the first one:

--- with_annotations.js
+++ with_annotations.js
@@ -338,79 +338,79 @@
 };

 // @ngInject
 function foo($scope) {
+}
-}
 foo.$inject = ["$scope"];

continues

(full diff here)

Is it only failing to me?

Annotate anonymous functions inside a closure

We have some coffeescript that looks like this:

class MyThing
  open: ->
    $modal.open
      templateUrl: "path/to/template.html"
      controller: "SomeController"
      resolve:
        collection: (CollectionClass) => CollectionClass.query()

This compiles to something like:

      MyThing.prototype.open = function() {
        return $modal.open({
          templateUrl: "path/to/template.html",
          controller: "SomeController",
          resolve: {
            collection: (function(_this) {
              return function(CollectionClass) {
                return CollectionClass.query();
              };
            })(this)
          }
        });
      };

The problem is that the CollectionClass doesn't get annotated. In this example, coffeescript's "fat arrow" isn't needed. However, the general problem is that you can't use dependency injection on fat arrow anonymous functions.

Support module object returned from a function

Since I use RequireJS for modules I usually do this:

define(function(require) {
  require('app-module')
  .controller('SomeCtrl', function($scope) { /* ... */ });
});

It doesn't work with ng-annotate, but it works if I do

define(function(require) {
  var module = require('app-module')
  module.controller('SomeCtrl', function($scope) { /* ... */ });
});

Can it be possible to support this kind of cases where the module is returned by a function?

Sourcemaps not pointing correctly with gulp

Almost identical to @luckylooke's post here gulp-sourcemaps/gulp-sourcemaps#19

I have a gulp workflow that looks something like this

 var pl = require('gulp-load-plugins')();

 gulp.task('scripts', function() {
     return gulp.src(watched.scripts)
    .pipe(pl.sourcemaps.init())
    .pipe(pl.concat('scripts.js'))
    .pipe(pl.ngAnnotate())
    .pipe(pl.uglify())
    .pipe(pl.sourcemaps.write('.'))
    .pipe(gulp.dest('./dist/scripts/'))
    .pipe(pl.livereload());
 });

In Chrome, the file referenced opposite a console.log() output in the web console is a different file to the one that it should be, and if I click it, I find the cursor at the bottom of that file. So, it doesn't appear to be pointing correctly? I have it working fine without ng-annotate.

 ng-annotate: v0.9.9
 gulp-ng-annotate: v0.3.0

0.9.10 Existing Injection Missed and ng-annotate Creates a Duplicate

Notice that the func extendExceptionHandler gets injection even though it already had it. This causes an error because the 2nd parm was actually a shortened name (which is why i explicitly annotated it).

    // already had this
    extendExceptionHandler.$inject = ['$delegate', 'exceptionConfig', 'logger'];

    / ng-annotate added this
    extendExceptionHandler.$inject = ['$delegate', 'exConfig', 'logger'];

This is the input

(function () {
    'use strict';

    angular
        .module('blocks.exception')
        .provider('exceptionConfig', exceptionConfigProvider)
        .config(['$provide', exceptionConfig]);

    function exceptionConfigProvider () {
        this.config = {};

        this.$get = function () {
            return {
                config: this.config
            };
        };
    }

    function exceptionConfig ($provide) {
        $provide.decorator('$exceptionHandler', extendExceptionHandler);
    }

    extendExceptionHandler.$inject = ['$delegate', 'exceptionConfig', 'logger'];

    function extendExceptionHandler($delegate, exConfig, logger) {
        var appErrorPrefix = exConfig.config.appErrorPrefix || '';
        return function (exception, cause) {
            $delegate(exception, cause);
            var errorData = { exception: exception, cause: cause };
            var msg = appErrorPrefix + exception.message;
            logger.error(msg, errorData);
        };
    }

})();

and this is the output

(function () {
    'use strict';

    angular
        .module('blocks.exception')
        .provider('exceptionConfig', exceptionConfigProvider)
        .config(['$provide', exceptionConfig]);

    function exceptionConfigProvider () {
        this.config = {};

        this.$get = function () {
            return {
                config: this.config
            };
        };
    }

    function exceptionConfig ($provide) {
        $provide.decorator('$exceptionHandler', extendExceptionHandler);
    }

    extendExceptionHandler.$inject = ['$delegate', 'exceptionConfig', 'logger'];

    function extendExceptionHandler($delegate, exConfig, logger) {
        var appErrorPrefix = exConfig.config.appErrorPrefix || '';
        return function (exception, cause) {
            $delegate(exception, cause);
            var errorData = { exception: exception, cause: cause };
            var msg = appErrorPrefix + exception.message;
            logger.error(msg, errorData);
        };
    }
    extendExceptionHandler.$inject = ['$delegate', 'exConfig', 'logger'];

})();

Module config function argument is not annotated automatically

ng-annotate did a fantastic job of annotating our app (very large and uses lots of different inject scenarios) but missed this one (I did a reduced test case with just the below code):

// declare main app
angular.module('app',[
    // declare dependencies
], function($interpolateProvider) {
    // change template echo tags due to use of Twig
    $interpolateProvider.startSymbol('[[');
    $interpolateProvider.endSymbol(']]');
});

should become:

// declare main app
angular.module('app',[
    // declare dependencies
], ['$interpolateProvider', function($interpolateProvider) {
    // change template echo tags due to use of Twig
    $interpolateProvider.startSymbol('[[');
    $interpolateProvider.endSymbol(']]');
}]);

To fix manually you can add an /*@ngInject*/ comment (or use a separate config function) :

angular.module('app',[
    // declare dependencies
], /*@ngInject*/ function($interpolateProvider) {
    // change template echo tags due to use of Twig
    $interpolateProvider.startSymbol('[[');
    $interpolateProvider.endSymbol(']]');
});

Provide workaround for poor comments handling in CoffeeScript (### @ngInject ###)

Hey, me again :)
We've just tested your recent changes (#40) and got another problem related to how CoffeeScript transforms sources.

Here's what happens: http://coffeescript.org/#try:%23%23%23%20%40ngInject%20%23%23%23%0Af%20%3D%20(%24scope)%20-%3E

For functions assignment expression CS generates 3 lines: var declaration, empty line, and the assignment itself. This isn't that stupid as actually CS collects all variables and hoists their declaration to the top of the scope. But in our case it breaks ngAnnotate which sees var declaration in the next line.

Is it possible you add an option that'll tell ngAnnotate to scan for the first line that matches function assignment and ignore those in between that don't?

Components with variable names get missed

Switching from ng-min to ng-annotate breaks our applications. We often use variables in our component names, but ng-annotate doesn't catch them. For instance,

var componentName = 'BrokenCtrl',
    module = angular.module('myApp.' + componentName, []);

module.controller(componentName, function ($scope) {
});

npm install ng-annotate failing

Reference point.
btford/ngmin#54 (comment)

Okey, tried to install ng-annotate:

> sudo npm update -g
> rm -fr node_modules/
> npm install ng-annotate
npm http GET https://registry.npmjs.org/ng-annotate
npm http 304 https://registry.npmjs.org/ng-annotate
npm http GET https://registry.npmjs.org/alter
npm http GET https://registry.npmjs.org/optimist
npm http GET https://registry.npmjs.org/simple-fmt
npm http GET https://registry.npmjs.org/ordered-ast-traverse
npm http GET https://registry.npmjs.org/simple-is
npm http GET https://registry.npmjs.org/priorityqueuejs
npm http GET https://registry.npmjs.org/tryor
npm http GET https://registry.npmjs.org/esprima
npm http 304 https://registry.npmjs.org/optimist
npm http 304 https://registry.npmjs.org/alter
npm http 304 https://registry.npmjs.org/simple-fmt
npm http 304 https://registry.npmjs.org/simple-is
npm http 304 https://registry.npmjs.org/ordered-ast-traverse
npm http 304 https://registry.npmjs.org/priorityqueuejs
npm http 304 https://registry.npmjs.org/tryor
npm http 304 https://registry.npmjs.org/esprima
npm http GET https://registry.npmjs.org/ordered-esprima-props
npm http GET https://registry.npmjs.org/stable
npm http 304 https://registry.npmjs.org/ordered-esprima-props
npm http 304 https://registry.npmjs.org/stable
npm ERR! Error: ENOENT, lstat '/home/kari/work/projects/ruby/external/ngannotate-rails/node_modules/ng-annotate/node_modules/optimist/test/parse_modified.js'
npm ERR! If you need help, you may report this log at:
npm ERR!     <http://github.com/isaacs/npm/issues>
npm ERR! or email it to:
npm ERR!     <[email protected]>

npm ERR! System Linux 3.11.10-7-desktop
npm ERR! command "/usr/bin/node" "/usr/bin/npm" "install" "ng-annotate"
npm ERR! cwd /home/kari/work/projects/ruby/external/ngannotate-rails
npm ERR! node -v v0.10.5
npm ERR! npm -v 1.2.18
npm ERR! path /home/kari/work/projects/ruby/external/ngannotate-rails/node_modules/ng-annotate/node_modules/optimist/test/parse_modified.js
npm ERR! fstream_path /home/kari/work/projects/ruby/external/ngannotate-rails/node_modules/ng-annotate/node_modules/optimist/test/parse_modified.js
npm ERR! fstream_type File
npm ERR! fstream_class FileWriter
npm ERR! code ENOENT
npm ERR! errno 34
npm ERR! fstream_stack /usr/lib64/node_modules/npm/node_modules/fstream/lib/writer.js:284:26
npm ERR! fstream_stack Object.oncomplete (fs.js:107:15)
npm ERR! Error: ENOENT, lstat '/home/kari/work/projects/ruby/external/ngannotate-rails/node_modules/ng-annotate/node_modules/esprima/esprima.js'
npm ERR! If you need help, you may report this log at:
npm ERR!     <http://github.com/isaacs/npm/issues>
npm ERR! or email it to:
npm ERR!     <[email protected]>

npm ERR! System Linux 3.11.10-7-desktop
npm ERR! command "/usr/bin/node" "/usr/bin/npm" "install" "ng-annotate"
npm ERR! cwd /home/kari/work/projects/ruby/external/ngannotate-rails
npm ERR! node -v v0.10.5
npm ERR! npm -v 1.2.18
npm ERR! path /home/kari/work/projects/ruby/external/ngannotate-rails/node_modules/ng-annotate/node_modules/esprima/esprima.js
npm ERR! fstream_path /home/kari/work/projects/ruby/external/ngannotate-rails/node_modules/ng-annotate/node_modules/esprima/esprima.js
npm ERR! fstream_type File
npm ERR! fstream_class FileWriter
npm ERR! code ENOENT
npm ERR! errno 34
npm ERR! fstream_stack /usr/lib64/node_modules/npm/node_modules/fstream/lib/writer.js:284:26
npm ERR! fstream_stack Object.oncomplete (fs.js:107:15)
npm ERR! error rolling back Error: ENOTEMPTY, rmdir '/home/kari/work/projects/ruby/external/ngannotate-rails/node_modules/ng-annotate'
npm ERR! error rolling back  [email protected] { [Error: ENOTEMPTY, rmdir '/home/kari/work/projects/ruby/external/ngannotate-rails/node_modules/ng-annotate']
npm ERR! error rolling back   errno: 53,
npm ERR! error rolling back   code: 'ENOTEMPTY',
npm ERR! error rolling back   path: '/home/kari/work/projects/ruby/external/ngannotate-rails/node_modules/ng-annotate' }
npm ERR! Error: No compatible version found: ordered-esprima-props@'^1.0.0'
npm ERR! Valid install targets:
npm ERR! ["1.0.0"]
npm ERR!     at installTargetsError (/usr/lib64/node_modules/npm/lib/cache.js:685:10)
npm ERR!     at /usr/lib64/node_modules/npm/lib/cache.js:607:10
npm ERR!     at saved (/usr/lib64/node_modules/npm/node_modules/npm-registry-client/lib/get.js:138:7)
npm ERR!     at Object.oncomplete (fs.js:107:15)
npm ERR! If you need help, you may report this log at:
npm ERR!     <http://github.com/isaacs/npm/issues>
npm ERR! or email it to:
npm ERR!     <[email protected]>

npm ERR! System Linux 3.11.10-7-desktop
npm ERR! command "/usr/bin/node" "/usr/bin/npm" "install" "ng-annotate"
npm ERR! cwd /home/kari/work/projects/ruby/external/ngannotate-rails
npm ERR! node -v v0.10.5
npm ERR! npm -v 1.2.18
npm ERR! 
npm ERR! Additional logging details can be found in:
npm ERR!     /home/kari/work/projects/ruby/external/ngannotate-rails/npm-debug.log
npm ERR! not ok code 0

Any idea about that? Investigating...

Support 'this' alias in providers

A very common pattern is to create an alias for this at the beginning of a provider definition (usually named self) and then use that alias throughout the file.

Currently, ng-annotate doesn't annotate $get when set through an alias:

angular.module("providers").provider("myProvider", function () {
    var self = this;

    //Won't be annotated
    self.$get = function ($rootScope) {
        //...
    };
});

Of course there is an easy workaround:

angular.module("providers").provider("myProvider", function () {
    var self = this;

    //Will be annotated
    this.$get = function ($rootScope) {
        //...
    };
});

But it would be handy to be able to keep using self.

I realize that supporting arbitrary alias for this may increase the complexity of ng-annotate, so I propose that only self is supported given that it is the most common alias.

Support for $injector.instantiate?

Hi - firstly, thanks for ng-annotate - great work.

Secondly, per the README I am requesting support for $injector.instantiate, or at least raising the issue for debate.

The use case
In my application I am using CoffeeScript classes heavily. Even my service definitions are classes. Using extends I can define a common base service class, and then use dependency injection to reference the base class in a concrete implementation.

By way of a pared down example:

angular.module('myApp').service 'A', ($injector, BaseServiceClass, AnotherClass) ->
  class AService extends BaseServiceClass
    constructor: (@$timeout, @$rootScope) ->

    do_stuff: ->
      return new AnotherClass

  $injector.instantiate AService

Leaving out the boilerplate CoffeeScript function definitions for __extends etc, this translates to:

angular.module('myApp').service('A', function($injector, BaseServiceClass, AnotherClass) {
  var AService;
  AService = (function(_super) {
    __extends(AService, _super);

    function AService($timeout, $rootScope) {
      this.$timeout = $timeout;
      this.$rootScope = $rootScope;
    }

    AService.prototype.do_stuff = function() {
      return new AnotherClass;
    };

    return AService;

  })(BaseServiceClass);
  return $injector.instantiate(AService);
});

At this point I fear the title for this issue may be slightly misleading, because what really needs to be supported here is automatic detection of types that are instantiated by $injector.instantiate. This may be a bridge too far....

I have a workaround, which is to annotate the constructors using block comments. Hence my example becomes:

angular.module('myApp').service 'A', ($injector, BaseServiceClass, AnotherClass) ->
  class AService extends BaseServiceClass
    ###
    @ngInject
    ###
    constructor: (@$timeout, @$rootScope) ->

    do_stuff: ->
      return new AnotherClass

  $injector.instantiate AService

Would support for $injector.instantiate be feasible? Or am I left to annotate my constructors?

Thanks in advance.

Inserted foo.$inject = [..] statements are sometimes unreachable

Reduced from #62:

Input:

~/projects/ng-annotate % cat tests-issues/issue63.js
function outer() {
    return {
        controller: MyCtrl,
    };

    // @ngInject
    function MyCtrl(a) {
    }
}

Current output:

~/projects/ng-annotate % ./ng-annotate-harmony -a tests-issues/issue63.js
function outer() {
    return {
        controller: MyCtrl,
    };

    // @ngInject
    function MyCtrl(a) {
    }
    MyCtrl.$inject = ["a"];
}

Expected output:

~/projects/ng-annotate % ./ng-annotate-harmony -a tests-issues/issue63.js
function outer() {
    MyCtrl.$inject = ["a"];
    return {
        controller: MyCtrl,
    };

    // @ngInject
    function MyCtrl(a) {
    }
}

Support referenced function declaration

A common pattern a lot of Angular developers I know (myself included) utilise a pattern like this:

function SomeCtrl () {

}
angular
  .module('app', [])
  .controller('SomeCtrl', SomeCtrl);

Currently, to make this work we have to do:

// @ngInject
function SomeCtrl () {

}
angular
  .module('app', [])
  .controller('SomeCtrl', SomeCtrl);

What would the implications be for getting this working with ng-annotate without using an /** @ngInject */ comment? As the method above becomes more popular, I think one of the main downsides to adoption are having to use the comment - is there a way ng-annotate can lookup the function based on it's name based on the scope?

Not working with angular.provider

Hello,

The dependency injection replacement seems to work fine with most of the angular calls, but it's not replacing in providers

example :

 angular.module('common').provider("dateService", function($serverDateFormat)

is left as it.

Support ES6 syntax

Using ES6 arrow functions causes parse errors in ng-annotate.

Running ng-annotate after transpilation is not possible due to Traceur removing comments, meaning explicit @ngAnnotate markers go missing.

Allow explicit annotation for function assignment?

This works

/* @ngInject */
var f = function($scope) {
  return $scope.x = 1;
};

While this doesn't:

var f;

/* @ngInject */
f = function($scope) {
  return $scope.x = 1;
};

And consequently nor does this

/* @ngInject */
module.exports = function($scope) {
  return $scope.x = 1;
};

We write our code in CoffeeScript and CS doesn't have inline comments. We organize our code with CommonJS (browserify), each controller, directive, etc. in separate file, then require'd and attached to module. So currently unfortunately we can't make use of ngAnnotate, but we'd love to. If you make it work with function expression that doesn't start with var that would help.

Inline controllers not being annotated inside constructor methods

Similar to the Bootstrap modals, I have custom modal factories that accept a controller within the constructor. Eg:

return new Modal({
  container: '.modal-container',
  templateUrl: 'example.html',  
  controller: function ($scope, someService) {
    // ...
  }
});

This syntax is not currently handled by ng-annotate. In the interim I am able to use the explicit inject notation which works fine:

return new Modal({
  container: '.modal-container',
  templateUrl: 'example.html',  
  controller: /* @ngInject */ function ($scope, someService) {
    // ...
  }
});

Obviously it would be nice if this was handled by default. Not an urgent problem but as per your README you said feel free to open an issue so here I am :)

ngInject not being transformed when directive controller is inside of directive closure

When a directive uses a controller and that controller needs // @ngInject syntax it is not being caught when it is defined within the directive closure.

(function () {
    'use strict';

    angular
        .module('app')
        .directive('foo', foo);

    /**
     * @returns {Object} - Directive definition object
     */
    function foo() {
        return {
            restrict: 'EA',
            scope: true,
            transclude: false,
            templateUrl: 'foo.html',
            controller: FooCtrl
        };

        /**
         * @ngInject
         */
        function FooCtrl($scope) {
            var vm = $scope.bar = {
                timeFormat: 'H:mma'
            };
        }
}
}());

Yet this does work when I moved the controller outside the directive.

(function () {
    'use strict';

    angular
        .module('app')
        .directive('foo', foo);

    /**
     * @returns {Object} - Directive definition object
     */
    function foo() {
        return {
            restrict: 'EA',
            scope: true,
            transclude: false,
            templateUrl: 'foo.html',
            controller: FooCtrl
        };
    }

    /**
     * @ngInject
     */
    function FooCtrl($scope) {
        var vm = $scope.bar = {
            timeFormat: 'H:mma'
        };
    }
}());

.config blocks don't get annotated

Angular .config blocks are not annotated with ng-annotate 0.4.0 which breaks apps using them. E.g. the following is not annotated:

(function () {
    'use strict';

    angular.module('cbnAnalytics', [
            'angulartics',
            'cbnAngularticsGoogleAnalytics',
        ])

        .config(function ($analyticsProvider) {
            $analyticsProvider.settings.pageTracking.basePath = window.settings.polonaUrl.slice(0, -1);
        });
})();

Do not annotate ui-router's $urlRouterProvider.otherwise

Currently, this:

$urlRouterProvider.otherwise(function ($injector) {
  //...
});

is being annotated into:

$urlRouterProvider.otherwise(["$injector", function ($injector) {
  //...
}]);

But ui-router expects a function:

this.otherwise =
    function (rule) {
      if (isString(rule)) {
        var redirect = rule;
        rule = function () { return redirect; };
      }
      else if (!isFunction(rule)) throw new Error("'rule' must be a function");
      otherwise = rule;
      return this;
    };

and already passes $injector as a parameter to otherwise:

function update() {
        function check(rule) {
          var handled = rule($injector, $location);
          if (handled) {
            if (isString(handled)) $location.replace().url(handled);
            return true;
          }
          return false;
        }
        var n=rules.length, i;
        for (i=0; i<n; i++) {
          if (check(rules[i])) return;
        }
        // always check otherwise last to allow dynamic updates to the set of rules
        if (otherwise) check(otherwise);
      }

I'm not being able to keep ng-annotate from annotating this by using:

regexp: /^((?!otherwise).)*$/

I probably misunderstood the regexp option, though.

Workaround:

var urlRouterProvider = $urlRouterProvider;
urlRouterProvider.otherwise(function ($injector) {
  //...
});

Update README.md

You may add this into README.md.

* [Rails](http://rubyonrails.org/): [ngannotate-rails](https://rubygems.org/gems/ngannotate-rails) by [Kari Ikonen](https://github.com/kikonen)

did I befoul something?

Getting this now...

[boneskull@lectroid:~/projects/beanstalk]$ sudo npm install -g ng-annotate
npm http GET https://registry.npmjs.org/ng-annotate
npm http 304 https://registry.npmjs.org/ng-annotate
npm http GET https://registry.npmjs.org/ast-traverse
npm http GET https://registry.npmjs.org/alter
npm http GET https://registry.npmjs.org/simple-fmt
npm http GET https://registry.npmjs.org/simple-is
npm http GET https://registry.npmjs.org/tryor
npm http GET https://registry.npmjs.org/esprima
npm http GET https://registry.npmjs.org/optimist
npm http 304 https://registry.npmjs.org/simple-is
npm http 304 https://registry.npmjs.org/alter
npm http 304 https://registry.npmjs.org/ast-traverse
npm http 304 https://registry.npmjs.org/tryor
npm http 304 https://registry.npmjs.org/esprima
npm http 304 https://registry.npmjs.org/optimist
npm http 304 https://registry.npmjs.org/simple-fmt
npm http GET https://registry.npmjs.org/stable
npm http GET https://registry.npmjs.org/wordwrap
npm http GET https://registry.npmjs.org/minimist
npm http 304 https://registry.npmjs.org/stable
npm http 304 https://registry.npmjs.org/wordwrap
npm http 304 https://registry.npmjs.org/minimist
npm ERR! Error: ENOENT, chmod '/usr/local/lib/node_modules/ng-annotate/build/es5/ng-annotate'
npm ERR! If you need help, you may report this *entire* log,
npm ERR! including the npm and node versions, at:
npm ERR!     <http://github.com/npm/npm/issues>

npm ERR! System Darwin 13.1.0
npm ERR! command "node" "/usr/local/bin/npm" "install" "-g" "ng-annotate"
npm ERR! cwd /Volumes/samara/projects/boneskull/beanstalk
npm ERR! node -v v0.10.26
npm ERR! npm -v 1.4.3
npm ERR! path /usr/local/lib/node_modules/ng-annotate/build/es5/ng-annotate
npm ERR! code ENOENT
npm ERR! errno 34
npm ERR! 
npm ERR! Additional logging details can be found in:
npm ERR!     /Volumes/samara/projects/boneskull/beanstalk/npm-debug.log
npm ERR! not ok code 0

Obviously the build isn't happening, so it can't find the file to install.

Provide info about annotated functions

This is a loose idea but I often add a service to dependencies of another one and then remove its uses but forget to remove the injection. Now, linters often have an option to report unused parameters of functions not only at the end of them, e.g. see:
http://eslint.org/docs/rules/no-unused-vars.html
with {"args": "all"} but then I'd have lots of false positives since in case of event handlers, replace functions on strings etc. we're sometimes interested in a second parameter but the first still has to be there.

Since ng-annotate already figures out which functions need to be annotated, I wonder if it was possible to pass this info along in some ways so that it'd be possible to check for unused injections in outside projects.

Or maybe ng-annotate could do this checking on its own? It rarely makes sense to inject components that aren't used in the code after all...

Regression: ng-annotate 0.9 annotates Lo-Dash methods invocations

Newest ng-annotate converts this:

notesForCurrentPage = _.filter(notes, function (note) {
    return note.page.uid === page.uid;
});

to this:

notesForCurrentPage = _.filter(notes, ["note", function (note) {
    return note.page.uid === page.uid;
}]);

This code has nothing to do with Angular and breaks Lo-Dash.

I suspect the annotating algorithm became too aggressive recently.

Support ui-router non-literal state config

In order to link states together, it is often useful to have named references to the states.

var state1Config = {
  name: 'state1',
  url: '/'
  controller: function($scope) { ... }
};
var state2Config = {
  name: 'state2',
  parent: state1Config,
  url: '/posts',
  controller: function($scope) { ... }
};
$stateProvider.state(state1Config);
$stateProvider.state(state2Config);

How can I help ng-annotate recognize and augment these config objects? By the time the parser reaches the $stateProvider.state calls, the relevant AssignmentExpression or VariableDeclaration has already passed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.