mirror of
https://github.com/KevinMidboe/linguist.git
synced 2025-12-28 21:01:00 +00:00
CoffeeScript JS guessing
This commit is contained in:
@@ -150,6 +150,8 @@ module Linguist
|
|||||||
# Generated source code is supressed in diffs and is ignored by
|
# Generated source code is supressed in diffs and is ignored by
|
||||||
# langauge statistics.
|
# langauge statistics.
|
||||||
#
|
#
|
||||||
|
# Requires Blob#data
|
||||||
|
#
|
||||||
# Includes:
|
# Includes:
|
||||||
# - XCode project XML files
|
# - XCode project XML files
|
||||||
# - Minified JavaScript
|
# - Minified JavaScript
|
||||||
@@ -158,6 +160,8 @@ module Linguist
|
|||||||
def generated?
|
def generated?
|
||||||
if ['.xib', '.nib', '.pbxproj'].include?(pathname.extname)
|
if ['.xib', '.nib', '.pbxproj'].include?(pathname.extname)
|
||||||
true
|
true
|
||||||
|
elsif generated_coffeescript?
|
||||||
|
true
|
||||||
elsif pathname.extname == '.js'
|
elsif pathname.extname == '.js'
|
||||||
# JS is minified if any lines are longer than 1000c
|
# JS is minified if any lines are longer than 1000c
|
||||||
lines.any? { |l| l.length > 1000 }
|
lines.any? { |l| l.length > 1000 }
|
||||||
@@ -166,6 +170,42 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Internal: Is the blob JS generated by CoffeeScript?
|
||||||
|
#
|
||||||
|
# Requires Blob#data
|
||||||
|
#
|
||||||
|
# CoffeScript is meant to output JS that would be difficult to
|
||||||
|
# tell if it was generated or not. Look for a number of patterns
|
||||||
|
# outputed by the CS compiler.
|
||||||
|
#
|
||||||
|
# Return true or false
|
||||||
|
def generated_coffeescript?
|
||||||
|
return unless pathname.extname == '.js'
|
||||||
|
|
||||||
|
if lines[0] == '(function() {' && # First line is module closure opening
|
||||||
|
lines[-2] == '}).call(this);' && # Second to last line closes module closure
|
||||||
|
lines[-1] == '' # Last line is blank
|
||||||
|
|
||||||
|
score = 0
|
||||||
|
|
||||||
|
lines.each do |line|
|
||||||
|
if line =~ /var /
|
||||||
|
# Underscored temp vars are likely to be Coffee
|
||||||
|
score += 1 * line.gsub(/(_fn|_i|_len|_ref|_results)/).count
|
||||||
|
|
||||||
|
# bind and extend functions are very Coffee specific
|
||||||
|
score += 3 * line.gsub(/(__bind|__extends|__hasProp|__indexOf|__slice)/).count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Require a score of 3. This is fairly arbitrary. Consider
|
||||||
|
# tweaking later.
|
||||||
|
score >= 3
|
||||||
|
else
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Public: Should the blob be indexed for searching?
|
# Public: Should the blob be indexed for searching?
|
||||||
#
|
#
|
||||||
# Excluded:
|
# Excluded:
|
||||||
|
|||||||
21
test/fixtures/blob/coffee/classes.coffee
vendored
Normal file
21
test/fixtures/blob/coffee/classes.coffee
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
class Animal
|
||||||
|
constructor: (@name) ->
|
||||||
|
|
||||||
|
move: (meters) ->
|
||||||
|
alert @name + " moved " + meters + "m."
|
||||||
|
|
||||||
|
class Snake extends Animal
|
||||||
|
move: ->
|
||||||
|
alert "Slithering..."
|
||||||
|
super 5
|
||||||
|
|
||||||
|
class Horse extends Animal
|
||||||
|
move: ->
|
||||||
|
alert "Galloping..."
|
||||||
|
super 45
|
||||||
|
|
||||||
|
sam = new Snake "Sammy the Python"
|
||||||
|
tom = new Horse "Tommy the Palomino"
|
||||||
|
|
||||||
|
sam.move()
|
||||||
|
tom.move()
|
||||||
46
test/fixtures/blob/coffee/classes.js
vendored
Normal file
46
test/fixtures/blob/coffee/classes.js
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
(function() {
|
||||||
|
var Animal, Horse, Snake, sam, tom;
|
||||||
|
var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
|
||||||
|
for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
|
||||||
|
function ctor() { this.constructor = child; }
|
||||||
|
ctor.prototype = parent.prototype;
|
||||||
|
child.prototype = new ctor;
|
||||||
|
child.__super__ = parent.prototype;
|
||||||
|
return child;
|
||||||
|
};
|
||||||
|
Animal = (function() {
|
||||||
|
function Animal(name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
Animal.prototype.move = function(meters) {
|
||||||
|
return alert(this.name + " moved " + meters + "m.");
|
||||||
|
};
|
||||||
|
return Animal;
|
||||||
|
})();
|
||||||
|
Snake = (function() {
|
||||||
|
__extends(Snake, Animal);
|
||||||
|
function Snake() {
|
||||||
|
Snake.__super__.constructor.apply(this, arguments);
|
||||||
|
}
|
||||||
|
Snake.prototype.move = function() {
|
||||||
|
alert("Slithering...");
|
||||||
|
return Snake.__super__.move.call(this, 5);
|
||||||
|
};
|
||||||
|
return Snake;
|
||||||
|
})();
|
||||||
|
Horse = (function() {
|
||||||
|
__extends(Horse, Animal);
|
||||||
|
function Horse() {
|
||||||
|
Horse.__super__.constructor.apply(this, arguments);
|
||||||
|
}
|
||||||
|
Horse.prototype.move = function() {
|
||||||
|
alert("Galloping...");
|
||||||
|
return Horse.__super__.move.call(this, 45);
|
||||||
|
};
|
||||||
|
return Horse;
|
||||||
|
})();
|
||||||
|
sam = new Snake("Sammy the Python");
|
||||||
|
tom = new Horse("Tommy the Palomino");
|
||||||
|
sam.move();
|
||||||
|
tom.move();
|
||||||
|
}).call(this);
|
||||||
0
test/fixtures/blob/coffee/empty.coffee
vendored
Normal file
0
test/fixtures/blob/coffee/empty.coffee
vendored
Normal file
3
test/fixtures/blob/coffee/empty.js
vendored
Normal file
3
test/fixtures/blob/coffee/empty.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
(function() {
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
1
test/fixtures/blob/coffee/hello.coffee
vendored
Normal file
1
test/fixtures/blob/coffee/hello.coffee
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
console.log "Hello, World!"
|
||||||
3
test/fixtures/blob/coffee/hello.js
vendored
Normal file
3
test/fixtures/blob/coffee/hello.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
(function() {
|
||||||
|
console.log("Hello, World!");
|
||||||
|
}).call(this);
|
||||||
28
test/fixtures/blob/coffee/intro.coffee
vendored
Normal file
28
test/fixtures/blob/coffee/intro.coffee
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# Assignment:
|
||||||
|
number = 42
|
||||||
|
opposite = true
|
||||||
|
|
||||||
|
# Conditions:
|
||||||
|
number = -42 if opposite
|
||||||
|
|
||||||
|
# Functions:
|
||||||
|
square = (x) -> x * x
|
||||||
|
|
||||||
|
# Arrays:
|
||||||
|
list = [1, 2, 3, 4, 5]
|
||||||
|
|
||||||
|
# Objects:
|
||||||
|
math =
|
||||||
|
root: Math.sqrt
|
||||||
|
square: square
|
||||||
|
cube: (x) -> x * square x
|
||||||
|
|
||||||
|
# Splats:
|
||||||
|
race = (winner, runners...) ->
|
||||||
|
print winner, runners
|
||||||
|
|
||||||
|
# Existence:
|
||||||
|
alert "I knew it!" if elvis?
|
||||||
|
|
||||||
|
# Array comprehensions:
|
||||||
|
cubes = (math.cube num for num in list)
|
||||||
37
test/fixtures/blob/coffee/intro.js
vendored
Normal file
37
test/fixtures/blob/coffee/intro.js
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
(function() {
|
||||||
|
var cubes, list, math, num, number, opposite, race, square;
|
||||||
|
var __slice = Array.prototype.slice;
|
||||||
|
number = 42;
|
||||||
|
opposite = true;
|
||||||
|
if (opposite) {
|
||||||
|
number = -42;
|
||||||
|
}
|
||||||
|
square = function(x) {
|
||||||
|
return x * x;
|
||||||
|
};
|
||||||
|
list = [1, 2, 3, 4, 5];
|
||||||
|
math = {
|
||||||
|
root: Math.sqrt,
|
||||||
|
square: square,
|
||||||
|
cube: function(x) {
|
||||||
|
return x * square(x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
race = function() {
|
||||||
|
var runners, winner;
|
||||||
|
winner = arguments[0], runners = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
||||||
|
return print(winner, runners);
|
||||||
|
};
|
||||||
|
if (typeof elvis !== "undefined" && elvis !== null) {
|
||||||
|
alert("I knew it!");
|
||||||
|
}
|
||||||
|
cubes = (function() {
|
||||||
|
var _i, _len, _results;
|
||||||
|
_results = [];
|
||||||
|
for (_i = 0, _len = list.length; _i < _len; _i++) {
|
||||||
|
num = list[_i];
|
||||||
|
_results.push(math.cube(num));
|
||||||
|
}
|
||||||
|
return _results;
|
||||||
|
})();
|
||||||
|
}).call(this);
|
||||||
@@ -116,6 +116,15 @@ class TestBlob < Test::Unit::TestCase
|
|||||||
# Minified JS
|
# Minified JS
|
||||||
assert !blob("jquery-1.6.1.js").generated?
|
assert !blob("jquery-1.6.1.js").generated?
|
||||||
assert blob("jquery-1.6.1.min.js").generated?
|
assert blob("jquery-1.6.1.min.js").generated?
|
||||||
|
|
||||||
|
# CoffeScript JS
|
||||||
|
|
||||||
|
# These examples are to basic to tell
|
||||||
|
assert !blob("coffee/empty.js").generated?
|
||||||
|
assert !blob("coffee/hello.js").generated?
|
||||||
|
|
||||||
|
assert blob("coffee/intro.js").generated?
|
||||||
|
assert blob("coffee/classes.js").generated?
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_vendored
|
def test_vendored
|
||||||
|
|||||||
Reference in New Issue
Block a user