javascript parser infrastructure for code quality analysis

53
JavaScript Parser Infrastructure for Code Quality Analysis Ariya Hidayat Twitter: @AriyaHidayat http://ariya.ofilabs.com

Upload: ariya-hidayat

Post on 15-Jan-2015

5.655 views

Category:

Technology


0 download

DESCRIPTION

 

TRANSCRIPT

Page 1: JavaScript Parser Infrastructure for Code Quality Analysis

JavaScript Parser Infrastructure for

Code Quality AnalysisAriya Hidayat

Twitter: @AriyaHidayathttp://ariya.ofilabs.com

Page 2: JavaScript Parser Infrastructure for Code Quality Analysis

Who Am I

Page 3: JavaScript Parser Infrastructure for Code Quality Analysis

Do you...

have a coding style/guidelines?use code quality tool such as JSLint or JSHint?actively prevent performance & coverage regressions?wish you could write your own quality rules?

Page 4: JavaScript Parser Infrastructure for Code Quality Analysis

Code Quality

Page 5: JavaScript Parser Infrastructure for Code Quality Analysis

High Quality: Practical Aspects

Avoid silly mistakes

Write readable code

Do not provoke ambiguities

Improve future maintenance

Learn better code pattern

Page 6: JavaScript Parser Infrastructure for Code Quality Analysis

Better Use of the Tools

EngineerTools

Feedback Cycle

Not everyone isa JavaScript ninja

•Boring•Repetitive•Time-consuming

Page 7: JavaScript Parser Infrastructure for Code Quality Analysis

From Spelling Checker to Grammar Enforcement Agent

Your so wrong,therefore you loose!

No misspelled word.Wrong choice of words!

Page 8: JavaScript Parser Infrastructure for Code Quality Analysis

Adaptive Quality Criteria

Explicit Implicit

Customize analysis optionsDefine new sets of rules

Infer from high-quality sampleObserve the engineer’s behavior

Page 9: JavaScript Parser Infrastructure for Code Quality Analysis

Next-Generation Code Quality Tools

To boldly analyze what no man has analyzed before...

Page 10: JavaScript Parser Infrastructure for Code Quality Analysis

Parser Infrastructure

Page 11: JavaScript Parser Infrastructure for Code Quality Analysis

JavaScript in the Browser

User Interface

Browser Engine

Graphics Stack

Data PersistenceRender Engine

JavaScript EngineNetworking I/O

Page 12: JavaScript Parser Infrastructure for Code Quality Analysis

JavaScript Engine Building Blocks

Virtual Machine/

InterpreterParser

Runtime

Source

Syntax Tree

Built-in objects,host objects, ...

Fast and conservative

Page 13: JavaScript Parser Infrastructure for Code Quality Analysis

Tokenization

keyword equal sign semicolon

identifier number

var answer = 42;

Page 14: JavaScript Parser Infrastructure for Code Quality Analysis

Syntax Tree

Variable Declaration

Identifier Literal Constant

answer 42

Page 15: JavaScript Parser Infrastructure for Code Quality Analysis

JavaScript Parser Written in JavaScript

UglifyJS

ZeParser

Esprima

TraceurNarcissus

Es-Lab

Page 16: JavaScript Parser Infrastructure for Code Quality Analysis

Produce Correct Output

ECMA-262 compliant Automatic semicolon insertion Strict Mode, e.g. “use strict” Unicode for identifiers

'use strict';var 日本語 = 1return 日本語

Page 17: JavaScript Parser Infrastructure for Code Quality Analysis

Heavily Tested > 500 unit tests Compatibility tests 100% code coverage Performance tests

Enforced during development

Page 18: JavaScript Parser Infrastructure for Code Quality Analysis

Sensible Syntax Tree

answer = 42

{ type: "Program", body: [ { type: "ExpressionStatement", expression: { type: "AssignmentExpression", operator: "=", left: { type: "Identifier", name: "answer" }, right: { type: "Literal", value: 42 } } } ]}

https://developer.mozilla.org/en/SpiderMonkey/Parser_API

http://esprima.org/demo/parse.html

Try online!

Page 19: JavaScript Parser Infrastructure for Code Quality Analysis

Syntax Tree Visualization

answer = 42

Page 20: JavaScript Parser Infrastructure for Code Quality Analysis

Specification, Parser Code, Syntax Tree

function parseWhileStatement() { var test, body;  expectKeyword('while'); expect('('); test = parseExpression(); expect(')'); body = parseStatement();  return { type: Syntax.WhileStatement, test: test, body: body };}

while ( Expression ) StatementECMA-262 Annex A.4

Page 21: JavaScript Parser Infrastructure for Code Quality Analysis

High Performance

Esprima

UglifyJS parse-js 922 ms

567 ms

620 ms

233 ms

Speed ComparisonChrome 18Internet Explorer 9

http://esprima.org/test/compare.html

Benchmark corpus:jQuery, Prototype, MooTools, ExtCore, ...

Page 22: JavaScript Parser Infrastructure for Code Quality Analysis

Syntax Node Location{ type: "ExpressionStatement", expression: { type: "AssignmentExpression", operator: "=", left: { type: "Identifier", name: "answer", range: [0, 6] }, right: { type: "Literal", value: 42, range: [9, 11] }, range: [0, 11] }, range: [0, 11]}

answer = 42

Page 23: JavaScript Parser Infrastructure for Code Quality Analysis

Fit for Code Regeneration https://github.com/Constellation/escodegen

Esprima EscodegenSource Source

Syntax Tree

Syntax TransformationShorten variable nameAutomatically inline short functionObfuscate

Page 24: JavaScript Parser Infrastructure for Code Quality Analysis

Easily Tweaked http://mbebenita.github.com/LLJS/LLJS: Low Level JavaScript

let x = 0;Block scope

let u8 flag;let i32 position;

struct Point { int x, y;};

Data types

let u16 *p = q;Pointers

Page 25: JavaScript Parser Infrastructure for Code Quality Analysis

Error Tolerant Useful for IDE, editors, ...

var msg = "Hello’;

person..age = 18;

 if (person.

 'use strict';with (person) {}

Mismatched quote

Too many dots

Incomplete, still typing

Strict mode violation

Page 26: JavaScript Parser Infrastructure for Code Quality Analysis

Handle the Comments

https://github.com/thejohnfreeman/jfdocDocumentation tool Code annotation

https://github.com/goatslacker/node-typedjs

// Life, Universe, and Everythinganswer = 42

comments: [ { range: [0, 34], type: "Line", value: " Life, Universe, and Everything" }]

Page 27: JavaScript Parser Infrastructure for Code Quality Analysis

Forward Looking Experimental ‘harmony’ branch

Object initializer shorthand

{ let x; const y = 0;}

Block scope

var point = {x, y};

Module

module MathExtra {

// do something

}

Destructuring assignment

point = {14, 3, 77};{x, y, z} = point;

Page 28: JavaScript Parser Infrastructure for Code Quality Analysis

Code Quality Tools

Page 29: JavaScript Parser Infrastructure for Code Quality Analysis

Syntax Tree Visualization

Block statement

http://esprima.org/demo/parse.html

Page 30: JavaScript Parser Infrastructure for Code Quality Analysis

Most Popular Keywordsthis

functionif

returnvar

elsefor

newin

typeofwhilecase

breaktry

catchdeletethrow

switchcontinue

defaultinstanceof

dovoid

finally 4

10

12

14

15

25

35

38

72

84

84

115

122

143

188

225

232

436

562

2116

2878

3063

3108

3229

http://ariya.ofilabs.com/2012/03/most-popular-javascript-keywords.html

var fs = require('fs'), esprima = require('esprima'), files = process.argv.splice(2); files.forEach(function (filename) { var content = fs.readFileSync(filename, 'utf-8'), tokens = esprima.parse(content, { tokens: true }).tokens;  tokens.forEach(function (token) { if (token.type === 'Keyword') { console.log(token.value); } });});

Page 31: JavaScript Parser Infrastructure for Code Quality Analysis

Most Popular Statements

http://ariya.ofilabs.com/2012/04/most-popular-javascript-statements.html

ExpressionStatementBlockStatement

IfStatementReturnStatement

VariableDeclarationFunctionDeclaration

ForStatementForInStatementWhileStatementBreakStatement

TryStatementEmptyStatementThrowStatement

SwitchStatementContinueStatementDoWhileStatementLabeledStatement 6

12

25

35

38

66

84

115

131

143

293

371

2116

2878

3063

6353

6728var fs = require('fs'), esprima = require('esprima'), files = process.argv.splice(2); files.forEach(function (filename) { var content = fs.readFileSync(filename, 'utf-8'), syntax = esprima.parse(content);  JSON.stringify(syntax, function (key, value) { if (key === 'type') { if (value.match(/Declaration$/) || value.match(/Statement$/)) { console.log(value); } } return value; });});

Page 32: JavaScript Parser Infrastructure for Code Quality Analysis

Identifier Length Distribution

http://ariya.ofilabs.com/2012/05/javascript-identifier-length-distribution.html

0

250

500

750

0 5 10 15 20 25 30 35 40 45

mean of the identifier length is 8.27 characters

prototype-1.7.0.0.js SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDINGprototype-1.7.0.0.js MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED jquery-1.7.1.js subtractsBorderForOverflowNotVisiblejquery.mobile-1.0.js getClosestElementWithVirtualBindingprototype-1.7.0.0.js HAS_EXTENDED_CREATE_ELEMENT_SYNTAX

Page 33: JavaScript Parser Infrastructure for Code Quality Analysis

“Code Linting”

https://github.com/jshint/jshint-nextAnother example: next-generation JSHint

var fs = require('fs'), esprima = require('./esprima'), files = process.argv.splice(2); files.forEach(function (filename) { var content = fs.readFileSync(filename, 'utf-8'), syntax = esprima.parse(content, { loc: true });  JSON.stringify(syntax, function (key, value) { if (key === 'test' && value.operator === '==') console.log('Line', value.loc.start.line); return value; });});

if (x == 9) { // do Something}

Not a strict equal

Page 34: JavaScript Parser Infrastructure for Code Quality Analysis

Strict Mode Checking

http://ariya.ofilabs.com/2012/03/strict-mode-checks-with-esprima.html

'use strict';block = { color: 'blue', height: 20, width: 10, color: 'red'};

Duplicate data property in object literal not allowed in strict mode

Page 35: JavaScript Parser Infrastructure for Code Quality Analysis

“Boolean Trap” Finderhttp://ariya.ofilabs.com/2011/08/hall-of-api-shame-boolean-trap.html

Can you make up your mind? treeItem.setState(true, false);

event.initKeyEvent("keypress", true, true, null, null, false, false, false, false, 9, 0);The more the merrier?

Obfuscated choice var volumeSlider = new Slider(false);

Double-negativecomponent.setHidden(false);filter.setCaseInsensitive(false);

Page 36: JavaScript Parser Infrastructure for Code Quality Analysis

Style Formatter https://github.com/fawek/codepainter

CodePainterSource

Sample code

Formatted source

Infer coding styles IndentationQuote for string literalWhitespace

Page 37: JavaScript Parser Infrastructure for Code Quality Analysis

Rewrite and Regenerate

var syntax = esprima.parse('answer = 42;');syntax.body[0].expression.right.value = 1337;escodegen.generate(syntax)

answer = 1337;

answer = 42;

https://github.com/Constellation/escodegen

Page 38: JavaScript Parser Infrastructure for Code Quality Analysis

Code Coverage

http://ariya.ofilabs.com/2012/03/javascript-code-coverage-and-esprima.html

x = 42;if (false) x = -1;

https://github.com/itay/node-coverhttps://github.com/coveraje/coverajehttps://github.com/pmlopes/coberturajs

Page 39: JavaScript Parser Infrastructure for Code Quality Analysis

Instrumentation for Coverage http://itay.github.com/snug_codecoverage_slides/

var a = 5;

{ __statement_ZyyqFc(1); var a = 5;}

foo();

{ __statement_ZyyqFc(2); __expression_kC$jur(3), foo();}

function foo() { ...};

function foo() { __block_n53cJc(1); ...}

Statement

Expression

Block

Page 40: JavaScript Parser Infrastructure for Code Quality Analysis

Non-Destructive Partial Source Modification

Modified

Intact Do not remove commentsPreserve indentation & other formatting

Add “contextual” informationInject or change function invocation

Page 41: JavaScript Parser Infrastructure for Code Quality Analysis

String Literal Quotes

http://ariya.ofilabs.com/2012/02/from-double-quotes-to-single-quotes.html

console.log('Hello')

[ { type: "Identifier", value: "console", range: [0, 7] }, { type: "Punctuator", value: ".", range: [7, 8] }, { type: "Identifier", value: "log", range: [8, 11] }, { type: "Punctuator", value: "(", range: [11, 12] }, { type: "String", value: ""Hello"", range: [12, 19] }, { type: "Punctuator", value: ")", range: [19, 19] }]

console.log("Hello")

May need proper escaping

List of tokens

Page 42: JavaScript Parser Infrastructure for Code Quality Analysis

Tracking the Scalability

http://ariya.ofilabs.com/2012/01/scalable-web-apps-the-complexity-issue.html

Array.prototype.swap = function (i, j) { var k = this[i]; this[i] = this[j]; this[j] = k;}

Array.prototype.swap = function (i, j) {Log({ name: 'Array.prototype.swap', lineNumber: 1, range: [23, 94] }); var k = this[i]; this[i] = this[j]; this[j] = k;}

Page 43: JavaScript Parser Infrastructure for Code Quality Analysis

Execution Tracing

http://ariya.ofilabs.com/2012/02/tracking-javascript-execution-during-startup.html

https://gist.github.com/1823129jQuery Mobile startup log

4640 function calls

jquery.js 26 jQuery jquery.js 103 init undefined, undefined, [object Object] jquery.js 274 each (Function) jquery.js 631 each [object Object], (Function), undefined jquery.js 495 isFunction [object Object] jquery.js 512 type [object Object]jquery.mobile.js 1857 [Anonymous]jquery.mobile.js 642 [Anonymous]jquery.mobile.js 624 enableMouseBindingsjquery.mobile.js 620 disableTouchBindings

Page 44: JavaScript Parser Infrastructure for Code Quality Analysis

Transpilation http://esprima.googlecode.com/git-history/harmony/demo/transpile.html

// Object literal property shorthand.function Point(x, y) { return { x: x, y: y };}

// Object literal property shorthand.function Point(x, y) { return { x, y };}

Harmony

ES 5.1Intact

Inserted fragment

Page 45: JavaScript Parser Infrastructure for Code Quality Analysis

Application Structure

Ext.define('My.sample.Person', { name: 'Mr. Unknown',  age: 42,

constructor: function(name) {},  walk: function(steps) {} run: function(steps) {}

});

http://www.sencha.com/learn/sencha-class-system/

Class manifest

{ className: 'My.sample.Person', functions: ['walk', 'run'], properties: ['name', 'age']}

Page 46: JavaScript Parser Infrastructure for Code Quality Analysis

Code Outline Eclipse

FunctionsVariables

Page 47: JavaScript Parser Infrastructure for Code Quality Analysis

Content Assist (aka Autocomplete, aka “Intellisense”)

http://contraptionsforprogramming.blogspot.com/2012/02/better-javascript-content-assist-in.html

Eclipse

Page 48: JavaScript Parser Infrastructure for Code Quality Analysis

Copy Paste Mistake

function inside(point, rect) { return (point.x >= rect.x1) && (point.y >= rect.y1) && (point.x <= rect.x2) && (point.y <= rect.y1);}

Wrong check

Page 49: JavaScript Parser Infrastructure for Code Quality Analysis

Refactoring Helper

// Add two numbersfunction add(firt, two) { return firt + two;}

// Add two numbersfunction add(first, two) { return first + two;}

Page 50: JavaScript Parser Infrastructure for Code Quality Analysis

Future

Tree traversal

“Richer” syntax treeScope analysis

Syntax transformation

Pattern Matching

Page 51: JavaScript Parser Infrastructure for Code Quality Analysis

Conclusion

Page 52: JavaScript Parser Infrastructure for Code Quality Analysis

Modern Parser

Smart editing

Source transformation

Minification & obfuscation

Instrumentation

Code coverage

Dependency analysis

Documentation generator

Conditional contracts

Page 53: JavaScript Parser Infrastructure for Code Quality Analysis

Thank You!

[email protected]

@AriyaHidayat

ariya.ofilabs.com