diff --git a/.travis.yml b/.travis.yml index 4d0c2351..52540b57 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,3 @@ -sudo: false before_install: script/travis/before_install rvm: - 1.9.3 diff --git a/lib/linguist.rb b/lib/linguist.rb index ff9fc3a2..3929efb9 100644 --- a/lib/linguist.rb +++ b/lib/linguist.rb @@ -6,3 +6,15 @@ require 'linguist/repository' require 'linguist/samples' require 'linguist/shebang' require 'linguist/version' + +class << Linguist + attr_accessor :instrumenter + + def instrument(*args, &bk) + if instrumenter + instrumenter.instrument(*args, &bk) + else + yield if block_given? + end + end +end diff --git a/lib/linguist/language.rb b/lib/linguist/language.rb index b500f2f6..da02b110 100644 --- a/lib/linguist/language.rb +++ b/lib/linguist/language.rb @@ -105,19 +105,31 @@ module Linguist # Bail early if the blob is binary or empty. return nil if blob.likely_binary? || blob.binary? || blob.empty? - # Call each strategy until one candidate is returned. - STRATEGIES.reduce([]) do |languages, strategy| - candidates = strategy.call(blob, languages) - if candidates.size == 1 - return candidates.first - elsif candidates.size > 1 - # More than one candidate was found, pass them to the next strategy. - candidates - else - # No candiates were found, pass on languages from the previous strategy. - languages + Linguist.instrument("linguist.detection", :blob => blob) do + # Call each strategy until one candidate is returned. + languages = [] + returning_strategy = nil + + STRATEGIES.each do |strategy| + returning_strategy = strategy + candidates = Linguist.instrument("linguist.strategy", :blob => blob, :strategy => strategy, :candidates => languages) do + strategy.call(blob, languages) + end + if candidates.size == 1 + languages = candidates + break + elsif candidates.size > 1 + # More than one candidate was found, pass them to the next strategy. + languages = candidates + else + # No candidates, try the next strategy + end end - end.first + + Linguist.instrument("linguist.detected", :blob => blob, :strategy => returning_strategy, :language => languages.first) + + languages.first + end end # Public: Get all Languages diff --git a/lib/linguist/languages.yml b/lib/linguist/languages.yml index 6fe05055..ce85eb08 100644 --- a/lib/linguist/languages.yml +++ b/lib/linguist/languages.yml @@ -356,7 +356,7 @@ Bro: C: type: programming - color: "#555" + color: "#555555" extensions: - .c - .cats @@ -994,7 +994,6 @@ GDScript: ace_mode: text GLSL: - group: C type: programming extensions: - .glsl @@ -1048,7 +1047,7 @@ Gentoo Eclass: ace_mode: sh Gettext Catalog: - type: programming + type: prose search_term: pot searchable: false aliases: @@ -2668,6 +2667,7 @@ Ruby: - .gemspec - .god - .irbrc + - .jbuilder - .mspec - .pluginspec - .podspec diff --git a/lib/linguist/popular.yml b/lib/linguist/popular.yml index 1a5cb750..afb68021 100644 --- a/lib/linguist/popular.yml +++ b/lib/linguist/popular.yml @@ -9,21 +9,21 @@ - CSS - Clojure - CoffeeScript -- Common Lisp -- Diff -- Emacs Lisp -- Erlang +- Go - HTML - Haskell - Java - JavaScript - Lua +- Matlab - Objective-C - PHP - Perl - Python +- R - Ruby -- SQL - Scala -- Scheme - Shell +- Swift +- TeX +- VimL diff --git a/lib/linguist/version.rb b/lib/linguist/version.rb index 86dd6961..9a84798b 100644 --- a/lib/linguist/version.rb +++ b/lib/linguist/version.rb @@ -1,3 +1,3 @@ module Linguist - VERSION = "4.4.2" + VERSION = "4.4.3" end diff --git a/samples/Ruby/index.json.jbuilder b/samples/Ruby/index.json.jbuilder new file mode 100644 index 00000000..26c7bc67 --- /dev/null +++ b/samples/Ruby/index.json.jbuilder @@ -0,0 +1,4 @@ +json.array!(@courts) do |court| + json.extract! court, :id, :name_r, :region, :region_r, :email, :website + json.url court_url(court, format: :json) +end diff --git a/script/travis/before_install b/script/travis/before_install index 442f6718..93ef383c 100755 --- a/script/travis/before_install +++ b/script/travis/before_install @@ -5,6 +5,8 @@ set -ex # Fetch all commits/refs needed to run our tests. git fetch origin master:master v2.0.0:v2.0.0 test/attributes:test/attributes test/master:test/master +sudo apt-get update + script/vendor-deb libicu48 libicu-dev if ruby -e 'exit RUBY_VERSION >= "2.0" && RUBY_VERSION < "2.1"'; then # Workaround for https://bugs.ruby-lang.org/issues/8074. We can't use this diff --git a/test/test_instrumentation.rb b/test/test_instrumentation.rb new file mode 100644 index 00000000..ab0615e5 --- /dev/null +++ b/test/test_instrumentation.rb @@ -0,0 +1,50 @@ +require_relative "./helper" + +class TestInstrumentation < Minitest::Test + include Linguist + + class LocalInstrumenter + Event = Struct.new(:name, :args) + + attr_reader :events + + def initialize + @events = [] + end + + def instrument(name, *args) + @events << Event.new(name, args) + yield if block_given? + end + end + + def setup + Linguist.instrumenter = LocalInstrumenter.new + end + + def teardown + Linguist.instrumenter = nil + end + + def test_detection_instrumentation_with_binary_blob + binary_blob = fixture_blob("Binary/octocat.ai") + Language.detect(binary_blob) + + # Shouldn't instrument this (as it's binary) + assert_equal 0, Linguist.instrumenter.events.size + end + + def test_modeline_instrumentation + blob = fixture_blob("Data/Modelines/ruby") + Language.detect(blob) + + detect_event = Linguist.instrumenter.events.last + detect_event_payload = detect_event[:args].first + + assert_equal 3, Linguist.instrumenter.events.size + assert_equal "linguist.detected", detect_event.name + assert_equal Language['Ruby'], detect_event_payload[:language] + assert_equal blob, detect_event_payload[:blob] + assert_equal Linguist::Strategy::Modeline, detect_event_payload[:strategy] + end +end diff --git a/vendor/grammars/NimLime b/vendor/grammars/NimLime index fac6b182..ae0b75d9 160000 --- a/vendor/grammars/NimLime +++ b/vendor/grammars/NimLime @@ -1 +1 @@ -Subproject commit fac6b182e8a92a65c9e144c578948d7b51048f26 +Subproject commit ae0b75d99a60f555e1b5cbab53eaed2ca9ca9101 diff --git a/vendor/grammars/PHP-Twig.tmbundle b/vendor/grammars/PHP-Twig.tmbundle index ad0f5147..f4f7529a 160000 --- a/vendor/grammars/PHP-Twig.tmbundle +++ b/vendor/grammars/PHP-Twig.tmbundle @@ -1 +1 @@ -Subproject commit ad0f5147e6d7ae70469084659cffcfd22575869e +Subproject commit f4f7529ac2a07527caa7c9154b87c96d17e18aa1 diff --git a/vendor/grammars/SublimePapyrus b/vendor/grammars/SublimePapyrus index e1b78aac..6f4e954f 160000 --- a/vendor/grammars/SublimePapyrus +++ b/vendor/grammars/SublimePapyrus @@ -1 +1 @@ -Subproject commit e1b78aacb6b0ab8b4c26ea897b128335f8ed939c +Subproject commit 6f4e954f35976f72f2a620af68aa0ba73e48478b diff --git a/vendor/grammars/dart-sublime-bundle b/vendor/grammars/dart-sublime-bundle index 21096f24..65c9cd9a 160000 --- a/vendor/grammars/dart-sublime-bundle +++ b/vendor/grammars/dart-sublime-bundle @@ -1 +1 @@ -Subproject commit 21096f24d8a34668d54ad31b8902ab5c709c1c07 +Subproject commit 65c9cd9a6540f6e47e5770314e13de7df05b2d2b diff --git a/vendor/grammars/elixir-tmbundle b/vendor/grammars/elixir-tmbundle index 9c63ff09..99910870 160000 --- a/vendor/grammars/elixir-tmbundle +++ b/vendor/grammars/elixir-tmbundle @@ -1 +1 @@ -Subproject commit 9c63ff09bd411d3e5c5a737145fc33d288804c9c +Subproject commit 99910870bb1cd095fc0af9010f018f1ae9e95b4e diff --git a/vendor/grammars/factor b/vendor/grammars/factor index fe2c2d23..e237b49f 160000 --- a/vendor/grammars/factor +++ b/vendor/grammars/factor @@ -1 +1 @@ -Subproject commit fe2c2d23de9e300d7cd1b04e139dfbdd2069d00a +Subproject commit e237b49f83c12aff3070c570404ef6bb19d1cc95 diff --git a/vendor/grammars/fsharpbinding b/vendor/grammars/fsharpbinding index a008fe9c..513db1c4 160000 --- a/vendor/grammars/fsharpbinding +++ b/vendor/grammars/fsharpbinding @@ -1 +1 @@ -Subproject commit a008fe9c64d454132941eb72334c52e4ad93266e +Subproject commit 513db1c44390c4967afe4dd220b9ec4f6a52cc3e diff --git a/vendor/grammars/grace-tmbundle b/vendor/grammars/grace-tmbundle index 6bea212a..2fba162c 160000 --- a/vendor/grammars/grace-tmbundle +++ b/vendor/grammars/grace-tmbundle @@ -1 +1 @@ -Subproject commit 6bea212a5843e152cd605ec6075eb7352cbeaf0d +Subproject commit 2fba162ce7cfb37421acb097be6aa31aaf414155 diff --git a/vendor/grammars/haxe-sublime-bundle b/vendor/grammars/haxe-sublime-bundle index 50c5aa0e..84a4fab1 160000 --- a/vendor/grammars/haxe-sublime-bundle +++ b/vendor/grammars/haxe-sublime-bundle @@ -1 +1 @@ -Subproject commit 50c5aa0e10f277f83dfe3d0e269a1043271be4df +Subproject commit 84a4fab144c185f4430f68cf10de35a7dfc79cb7 diff --git a/vendor/grammars/language-gfm b/vendor/grammars/language-gfm index 5f5df306..6ca2ea2a 160000 --- a/vendor/grammars/language-gfm +++ b/vendor/grammars/language-gfm @@ -1 +1 @@ -Subproject commit 5f5df3064c9dccbfd8dac8d260b0d4a843ac88a5 +Subproject commit 6ca2ea2ac50fe02cde1bcec114c66101129daab6 diff --git a/vendor/grammars/mercury-tmlanguage b/vendor/grammars/mercury-tmlanguage index 1cb8e949..cb57d42d 160000 --- a/vendor/grammars/mercury-tmlanguage +++ b/vendor/grammars/mercury-tmlanguage @@ -1 +1 @@ -Subproject commit 1cb8e94922803658040bc29aa732c1671e2afe5b +Subproject commit cb57d42dbe343d3809c3dd7946f28f6354a2687e diff --git a/vendor/grammars/restructuredtext.tmbundle b/vendor/grammars/restructuredtext.tmbundle index 43fc7b1f..608d8bcd 160000 --- a/vendor/grammars/restructuredtext.tmbundle +++ b/vendor/grammars/restructuredtext.tmbundle @@ -1 +1 @@ -Subproject commit 43fc7b1ff351d6733f7ce136aafe3091e77b4347 +Subproject commit 608d8bcdea179d4bf3def6244e0d9cf7705f2fea