Magic number detection for JavaScript

Overview

buddy.js

Magic number detection for javascript. Let Buddy sniff out the unnamed numerical constants in your code.

Build Status

Overview

We all know magic numbers are frowned upon as a programming practice. They may give no indication of their meaning, and when used multiple times, can result in future inconsistencies. They can expose you to the risk of typos, hinder maintenance and have an impact on readability. That's where Buddy comes in.

Buddy is a cli tool that's eager to find the magic numbers in your code. It accepts a list of paths to parse, and renders any found instances with the selected reporter. In the case of directories, they're walked recursively, and only .js files are analyzed. Any node_modules dirs are also ignored.

Since const is not widespread in JavaScript, it defaults to searching for numbers which are not the sole literal in an object expression or variable declaration. Furthermore, specific values can be ignored, such as 0 and 1, which are ignored by default.

intro-screenshot

Who's a good boy?

What are magic numbers?

Magic numbers are unnamed numerical constants, though the term can sometimes be used to refer to other literals as well. Take the following contrived example:

function getTotal(subtotal) {
  var beforeTax = subtotal + 9.99;
  return beforeTax + (beforeTax * 0.13);
}

In the above function, the meaning of the two numbers might not be clear. What is this 9.99 charge? In our case, let's say it's a shipping rate. And what about the 0.13? It's the sales tax. Buddy will highlight those two instances:

$ buddy example.js

example.js:2 | var beforeTax = subtotal + 9.99;
example.js:3 | return beforeTax + (beforeTax * 0.13);

 2 magic numbers found across 1 file

If the tax rate was used in multiple locations, it's prone to human error. And it might not be immediately clear that the 9.99 charge is a flat rate shipping cost, which can affect maintenance. So how would this be improved?

var FLAT_SHIPPING_COST = 9.99;
var SALES_TAX = 0.13;

function getTotal(subtotal) {
  var beforeTax = subtotal + FLAT_SHIPPING_COST;
  return beforeTax + (beforeTax * SALES_TAX);
}

Or, depending on your target platforms or browsers, by using the const keyword for variable declaration instead of var. While const is available in Node, you should take note of its browser compatibility for front end JavaScript.

$ buddy example.js

 No magic numbers found across 1 file

Installation

It can be installed via npm using:

npm install -g buddy.js

Also available: grunt-buddyjs, and gulp-buddy.js

Usage

Usage: buddy [options] <paths ...>

Options:

  -h, --help                             output usage information
  -V, --version                          output the version number
  -d, --detect-objects                   detect object expressions and properties
  -e, --enforce-const                    require literals to be defined using const
  -i, --ignore <numbers>                 list numbers to ignore (default: 0,1)
  -I, --disable-ignore                   disables the ignore list
  -r, --reporter [simple|detailed|json]  specify reporter to use (default: simple)
  -C, --no-color                         disables colors

If a .buddyrc file is located in the project directory, its values will be used in place of the defaults listed above. For example:

{
  "detectObjects": false,
  "enforceConst":  false,
  "ignore":        [0, 1, 2], // Use empty array to disable ignore
  "reporter":      "detailed"
}

Integration

You can easily run Buddy on your library source as part of your build. It will exit with an error code of 0 when no magic numbers were found. Otherwise it will return a positive error code, and result in a failing build. For example, with Travis CI, you can add the following two entries to your .travis.yml:

before_script:
  - "npm install -g buddy.js"

script:
  - "buddy ./path/to/src"

Reporters

For additional context, try using the detailed reporter. Or, for logging output and integration with your quality assurance process, the json reporter can be used.

detailed-reporter

Ignoring numbers

A magic number can be ignored in any of three ways:

  1. Its value is ignored using the --ignore flag
  2. The line includes the following comment buddy ignore:line
  3. The line is located between a buddy ignore:start and buddy ignore:end

Given the following example, two magic numbers exist that could be ignored:

var SECOND = 1000;
var MINUTE = 60 * SECOND;
var HOUR = 60 * MINUTE;

Using the command line option, you can run buddy with: buddy example.js --ignore 60. Or, if preferred, you can specify that the instances be ignored on a case-by-case basis:

var SECOND = 1000;
var MINUTE = 60 * SECOND; // buddy ignore:line
var HOUR = 60 * MINUTE; // buddy ignore:line

Or better yet, you can make use of directives to ignore all magic numbers within a range:

// buddy ignore:start
var SECOND = 1000;
var MINUTE = 60 * SECOND;
var HOUR = 60 * MINUTE;
// buddy ignore:end
Comments
  • Handle first line shebang

    Handle first line shebang

    Node allows executable scripts to use the unix shebang (#!/usr/bin/env node) convention. It seems buddy.js chokes on this, which is probably an issue with the upstream parser or the configuration thereof:

    { [SyntaxError: Unexpected character '#' (1:0)] pos: 0, loc: { line: 1, column: 0 }, raisedAt: 0 }
    
    opened by focusaurus 5
  • Has no method split

    Has no method split

    I've been having an issue with buddyjs recently where in my grunt task it will error out saying something along the lines of:

    Running "buddyjs:src" (buddyjs) task
    [TypeError: Object
    ## CONTENTS OF ONE OF MY JS FILES ##
     has no method 'split']
    Warning: Task "buddyjs:src" failed. Use --force to continue.
    
    Aborted due to warnings.
    

    Now this seems to be because its expecting a large string to split on newlines, however it's an object.

    Line of code that assumes this: https://github.com/danielstjules/buddy.js/blob/8558a9d5ed2098325b462d30895c9c2db0f5ea74/lib/detector.js#L152

    The method expects contents to be a string, where in this case it seems to be the raw buffer and not a string, causing the split on newlines to fail.

    opened by tglines 4
  • Add the ability to ignore on a case-by-case basis

    Add the ability to ignore on a case-by-case basis

    I have a case where I am converting seconds to ms. e.g.

    var MS = SECONDS * 1000;
    

    Currently, I'd have to rewrite 1000 as a const or ignore it everywhere. Instead, I'd like to be able to ignore that line with a comment.

    opened by mimshwright 4
  • Report negative numbers in const

    Report negative numbers in const

    Buddy.js report negative number even though they are stored in const :

    src/attachmentMappers/retailMappers.js:3  | const EMPTY_INDEX_OF = -1;
    
     1 magic number found across 34 files
    

    v0.9

    opened by jcare44 3
  • Doesn't report object literal attribtues

    Doesn't report object literal attribtues

    Consider the following file:

    var x = {
        statusCode: 200,
        y: function() {
            z = 100;
        }
    };
    

    Buddy doesn't report the 200 as being a magic number. Though it will report the 100.

    opened by tlhunter 3
  • Ignore comments doesn't work

    Ignore comments doesn't work

    Hi Daniel,

    I'm using buddy.js in version 0.7.0:

    ./node_modules/buddy.js/bin/buddy --version
    

    My source snippet is:

    return b = Math.random() * 16, (a === 'y' ? (b & 3 | 8) : (b | 0)).toString(16); // buddy ignore: line
    

    Calling buddy.js returns warnings:

    ./snippet.js:1 | return b = Math.random() * 16, (a === 'y' ? (b & 3 | 8) : (b | 0)).toString(16); // buddy ignore: line
    ./snippet.js:1 | return b = Math.random() * 16, (a === 'y' ? (b & 3 | 8) : (b | 0)).toString(16); // buddy ignore: line
    ./snippet.js:1 | return b = Math.random() * 16, (a === 'y' ? (b & 3 | 8) : (b | 0)).toString(16); // buddy ignore: line
    ./snippet.js:1 | return b = Math.random() * 16, (a === 'y' ? (b & 3 | 8) : (b | 0)).toString(16); // buddy ignore: line
    
     4 magic numbers found across 6 files
    

    Did I miss something?

    With kind regards Marco

    opened by m99coder 3
  • Buddy displays hex/octal numbers incorrectly

    Buddy displays hex/octal numbers incorrectly

    If you make a file with the following contents:

    console.log(0x1A + 0x02);
    console.log(071);
    

    The output from Buddy is rather interesting:

    $ buddy .
    
    ./test.js:1 | console.log(26 + 0x02);
    ./test.js:1 | console.log(0x1A + 2);
    ./test.js:2 | console.log(57);
    
    3 magic numbers found across 1 file
    

    Notice how the hex/octal numbers are converted to decimal before being logged.

    opened by tlhunter 2
  • buddy binary reports wrong version number

    buddy binary reports wrong version number

    Hi Daniel,

    unfortunately buddy binary returns wrong version number if called with:

    $ ./bin/buddy --version
    0.0.1
    

    Although dependencies are declared the following:

    "buddy.js": "^0.2.1"
    

    and the downloaded version contains 0.2.1 in it's own package.json.

    Maybe this issue is already fixed in newer versions.

    With kind regards Marco

    opened by m99coder 2
  • Unexpected token

    Unexpected token "*"

    NOTE: I know nodeJS v0.11.x does not have a stable release yet, so it is not really that important I guess?

    With ECMAScript 6, support for generators is added. Currently, this requires one to use the --harmony flag to run node scripts that make use of generators. There is an issue with buddy.js, because these functions are indicated by asterisk notation.

    function* foo(x) {
        yield x + 1;
    
        var y = yield null;
        return x + y;
    }
    

    The issue is that buddy.js notices an unexpected token (the *) and shuts down by this error.

    opened by Tessmore 2
  • gulp plugin

    gulp plugin

    Hello! For myself, I've created gulp plugin. Perhaps it may be necessary to someone else. It would be great if you added my plugin to README as grunt plugin.

    https://github.com/Semigradsky/gulp-buddy.js

    opened by Semigradsky 1
  • seperate concerns between file parse and code parse

    seperate concerns between file parse and code parse

    A common use case is to only use contents parsing instead of file path parsing. This patch separates concerns between reading file path and parsing contents.

    opened by pgilad 1
  • Add Related Section

    Add Related Section

    What is the change

    Add "Related Section" referencing ESlint's magic number rule.

    Purpose of Change

    1. Expose more people to the awesome-ness of no magic numbers.
    2. ESlint is constantly updating and maintaining their version of 'no magic numbers' linter rule that works with modern javascript & typescript. It seems like this repo hasn't been updated in a while.
    3. Most people when they search 'no magic numbers' in javascript frequently land here. It would be nice for them to also know that it exists in ESlint as part of a core rule.

    Questions

    Are you ok with putting a notice in the beginning of the README, indicating to user's that it's worth checking out ESlint's version in the spirit of getting more people exposed to 'no magic numbers'?

    opened by cliffordfajardo 0
  • Ignore path

    Ignore path

    I added a local version of jQuery to my a repo, and now Buddy is failing with over 60 magic numbers found.

    Is there any way to ignore a path?

    Or can --ignorePath be added as a cli option?

    Thank you!

    opened by dylanized 2
Releases(0.9.3)
Owner
Daniel St. Jules
Daniel St. Jules
For formatting, searching, and rewriting JavaScript.

jsfmt For formatting, searching, and rewriting JavaScript. Analogous to gofmt. Installation npm install -g jsfmt Usage $ jsfmt --help Usage: jsfmt [

Rdio 1.7k Dec 9, 2022
Find and fix problems in your JavaScript code.

ESLint Website | Configuring | Rules | Contributing | Reporting Bugs | Code of Conduct | Twitter | Mailing List | Chat Room ESLint is a tool for ident

ESLint 21.9k Dec 31, 2022
The JavaScript Code Quality Tool

JSLint, The JavaScript Code Quality Tool Douglas Crockford [email protected] 2019-03-15 jslint.js contains the jslint function. It parses and a

Douglas Crockford 3.5k Jan 6, 2023
🌟 JavaScript Style Guide, with linter & automatic code fixer

JavaScript Standard Style Sponsored by English • Español (Latinoamérica) • Français • Bahasa Indonesia • Italiano (Italian) • 日本語 (Japanese) • 한국어 (Ko

Standard JS 27.8k Dec 31, 2022
Beautifier for javascript

JS Beautifier This little beautifier will reformat and re-indent bookmarklets, ugly JavaScript, unpack scripts packed by Dean Edward’s popular packer,

null 8k Jan 3, 2023
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
Multiplies a number by zero. Useful for when you need to multiply a number by zero

multiply-by-zero Multiplies a number by zero. Useful for when you need to multiply a number by zero Please consider checking out the links of this pro

Dheirya Tyagi 2 Jul 3, 2022
jquery-input-mask-phone-number.js - A simple, easy jquery format phone number mask library

jquery-input-mask-phone-number A jQuery Plugin to make masks on input field to US phone format. Quick start 1. Add latest jQuery and jquery-input-mask

Raja Rama Mohan Thavalam 12 Aug 25, 2022
JavaScript syntax highlighter with language auto-detection and zero dependencies.

Highlight.js Highlight.js is a syntax highlighter written in JavaScript. It works in the browser as well as on the server. It can work with pretty muc

highlight.js 20.8k Jan 5, 2023
JavaScript API for face detection and face recognition in the browser and nodejs with tensorflow.js

face-api.js JavaScript face recognition API for the browser and nodejs implemented on top of tensorflow.js core (tensorflow/tfjs-core) Click me for Li

Vincent MĂĽhler 14.6k Jan 2, 2023
Flexible JavaScript library for creating squircley magic ✨

squircley.js squircley.js is the core squirclular magic ✨ from https://squircley.app wrapped up into a simple, 0 dependency JavaScript library. squirc

George Francis 87 Dec 24, 2022
A platform detection library.

Platform.js v1.3.6 A platform detection library that works on nearly all JavaScript platforms. Disclaimer Platform.js is for informational purposes on

BestieJS Modules 3.1k Dec 31, 2022
A library for prototyping realtime hand detection (bounding box), directly in the browser.

Handtrack.js View a live demo in your browser here. Handtrack.js is a library for prototyping realtime hand detection (bounding box), directly in the

Victor Dibia 2.7k Jan 3, 2023
Defacement detection with deep learning

In0ri is a defacement detection system utilizing a image-classification convolutional neural network. Introduction When monitoring a website, In0ri wi

Just4Fun Security 47 Nov 30, 2022
🛤 Detection of elements in viewport & smooth scrolling with parallax.

Locomotive Scroll Detection of elements in viewport & smooth scrolling with parallax effects. Installation ⚠️ Scroll-hijacking is a controversial prac

Locomotive 5.9k Dec 31, 2022
Ethereum smart contract gas cost waste pattern detection and patching tool

Ethereum smart contract gas cost waste pattern detection and patching tool

ibelab 4 Mar 23, 2022
Octoprint-Detector2 is a detection plugin that runs in locally your browser and emails you if it detects some spaghetti, stringing or blobs on your print

Octoprint-Detector2 is a detection plugin that runs in locally your browser and emails you if it detects some spaghetti, stringing or blobs on your print. All you need is an email account and a PC.

Mikulash 24 Jan 2, 2023
A facial recognition/detection app with Angular using Microsoft's Face API

Deja-Vu Overview Deja-Vu is a client side application generated with Angular CLI version 13. The core function of this application is to detect, recog

Wali Ullah 3 Jul 30, 2022