Merge branch 'master' into 2821-slim

This commit is contained in:
Arfon Smith
2016-03-17 10:23:59 -06:00
43 changed files with 199 additions and 76 deletions

View File

@@ -111,7 +111,7 @@ def git_linguist(args)
parser.parse!(args)
git_dir = `git rev-parse --git-dir`.strip
raise "git-linguist must be ran in a Git repository" unless $?.success?
raise "git-linguist must be ran in a Git repository (#{Dir.pwd})" unless $?.success?
wrapper = GitLinguist.new(git_dir, commit, incremental)
case args.pop

View File

@@ -9,8 +9,85 @@ require 'linguist/shebang'
require 'linguist/version'
class << Linguist
# Public: Detects the Language of the blob.
#
# blob - an object that includes the Linguist `BlobHelper` interface;
# see Linguist::LazyBlob and Linguist::FileBlob for examples
#
# Returns Language or nil.
def detect(blob)
# Bail early if the blob is binary or empty.
return nil if blob.likely_binary? || blob.binary? || blob.empty?
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
Linguist.instrument("linguist.detected", :blob => blob, :strategy => returning_strategy, :language => languages.first)
languages.first
end
end
# Internal: The strategies used to detect the language of a file.
#
# A strategy is an object that has a `.call` method that takes two arguments:
#
# blob - An object that quacks like a blob.
# languages - An Array of candidate Language objects that were returned by the
#     previous strategy.
#
# A strategy should return an Array of Language candidates.
#
# Strategies are called in turn until a single Language is returned.
STRATEGIES = [
Linguist::Strategy::Modeline,
Linguist::Shebang,
Linguist::Strategy::Filename,
Linguist::Heuristics,
Linguist::Classifier
]
# Public: Set an instrumenter.
#
# class CustomInstrumenter
# def instrument(name, payload = {})
# warn "Instrumenting #{name}: #{payload[:blob]}"
# end
# end
#
# Linguist.instrumenter = CustomInstrumenter
#
# The instrumenter must conform to the `ActiveSupport::Notifications`
# interface, which defines `#instrument` and accepts:
#
# name - the String name of the event (e.g. "linguist.detected")
# payload - a Hash of the exception context.
attr_accessor :instrumenter
# Internal: Perform instrumentation on a block
#
# Linguist.instrument("linguist.dosomething", :blob => blob) do
# # logic to instrument here.
# end
#
def instrument(*args, &bk)
if instrumenter
instrumenter.instrument(*args, &bk)
@@ -18,4 +95,5 @@ class << Linguist
yield
end
end
end

View File

@@ -6,7 +6,7 @@ require 'yaml'
module Linguist
# DEPRECATED Avoid mixing into Blob classes. Prefer functional interfaces
# like `Language.detect` over `Blob#language`. Functions are much easier to
# like `Linguist.detect` over `Blob#language`. Functions are much easier to
# cache and compose.
#
# Avoid adding additional bloat to this module.
@@ -325,7 +325,7 @@ module Linguist
#
# Returns a Language or nil if none is detected
def language
@language ||= Language.detect(self)
@language ||= Linguist.detect(self)
end
# Internal: Get the TextMate compatible scope for the blob

View File

@@ -313,6 +313,14 @@ module Linguist
end
end
disambiguate ".props" do |data|
if /^(\s*)(<Project|<Import|<Property|<?xml|xmlns)/i.match(data)
Language["XML"]
elsif /\w+\s*=\s*/i.match(data)
Language["INI"]
end
end
disambiguate ".r" do |data|
if /\bRebol\b/i.match(data)
Language["Rebol"]
@@ -346,7 +354,7 @@ module Linguist
end
disambiguate ".sql" do |data|
if /^\\i\b|AS \$\$|LANGUAGE '+plpgsql'+/i.match(data) || /SECURITY (DEFINER|INVOKER)/i.match(data) || /BEGIN( WORK| TRANSACTION)?;/i.match(data)
if /^\\i\b|AS \$\$|LANGUAGE '?plpgsql'?/i.match(data) || /SECURITY (DEFINER|INVOKER)/i.match(data) || /BEGIN( WORK| TRANSACTION)?;/i.match(data)
#Postgres
Language["PLpgSQL"]
elsif /(alter module)|(language sql)|(begin( NOT)+ atomic)/i.match(data) || /signal SQLSTATE '[0-9]+'/i.match(data)

View File

@@ -87,14 +87,6 @@ module Linguist
language
end
STRATEGIES = [
Linguist::Strategy::Modeline,
Linguist::Shebang,
Linguist::Strategy::Filename,
Linguist::Heuristics,
Linguist::Classifier
]
# Public: Detects the Language of the blob.
#
# blob - an object that includes the Linguist `BlobHelper` interface;
@@ -102,34 +94,8 @@ module Linguist
#
# Returns Language or nil.
def self.detect(blob)
# Bail early if the blob is binary or empty.
return nil if blob.likely_binary? || blob.binary? || blob.empty?
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
Linguist.instrument("linguist.detected", :blob => blob, :strategy => returning_strategy, :language => languages.first)
languages.first
end
warn "[DEPRECATED] `Linguist::Language.detect` is deprecated. Use `Linguist.detect`. #{caller[0]}"
Linguist.detect(blob)
end
# Public: Get all Languages

View File

@@ -3863,6 +3863,7 @@ XML:
- .osm
- .plist
- .pluginspec
- .props
- .ps1xml
- .psc1
- .pt

View File

@@ -1,3 +1,3 @@
module Linguist
VERSION = "4.7.6"
VERSION = "4.8.0"
end

View File

@@ -0,0 +1,31 @@
load 'plpgsql';
load 'plpgsql_lint';
DROP FUNCTION IF EXISTS list_sites();
CREATE OR REPLACE FUNCTION list_sites() RETURNS TABLE (fc json) AS
$func$
BEGIN
RETURN QUERY SELECT row_to_json(feat_col) FROM (
SELECT 'FeatureCollection' AS type, array_to_json(array_agg(feat)) AS features FROM (
SELECT DISTINCT ON (new_id) 'Feature' AS type, ST_ASGeoJSON(loc.geom)::json AS geometry, row_to_json(
(SELECT prop FROM (SELECT new_id) AS prop)) AS properties FROM location loc) AS feat) AS feat_col;
END;
$func$ LANGUAGE plpgsql;
DROP FUNCTION IF EXISTS get_observations(character varying, integer);
CREATE OR REPLACE FUNCTION get_observations(kind varchar, site_id integer) RETURNS TABLE (fc json) AS
$func$
BEGIN
IF kind = 'o2_abs' THEN
RETURN QUERY SELECT array_to_json(array_agg(row_to_json(obs))) FROM (
SELECT observation_date AS date, o2_abs AS value FROM oxygen WHERE new_id = site_id) AS obs;
ELSIF kind = 'o2_rel' THEN
RETURN QUERY SELECT array_to_json(array_agg(row_to_json(obs))) FROM (
SELECT observation_date AS date, o2_rel AS value FROM oxygen WHERE new_id = site_id) AS obs;
ELSIF kind = 'temp' THEN
RETURN QUERY SELECT array_to_json(array_agg(row_to_json(obs))) FROM (
SELECT observation_date AS date, temp AS value FROM oxygen WHERE new_id = site_id) AS obs;
END IF;
END;
$func$ LANGUAGE plpgsql;

29
samples/XML/Default.props Normal file
View File

@@ -0,0 +1,29 @@
<!--
***********************************************************************************************
Default.props
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
created a backup copy. Incorrect changes to this file will make it
impossible to load or build your projects from the command-line or the IDE.
Copyright (C) Microsoft Corporation. All rights reserved.
***********************************************************************************************
-->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Import Before -->
<Import Condition="Exists('$(MSBuildThisFileDirectory)ImportBefore\Default')" Project="$(MSBuildThisFileDirectory)ImportBefore\Default\*.props" />
<PropertyGroup>
<TargetOsAndVersion>Windows Phone Silverlight 8.1</TargetOsAndVersion>
<RealOSVersion>6.3</RealOSVersion>
<PlatformToolset Condition="'$(PlatformToolset)' == ''">v120</PlatformToolset>
<_PlatformToolsetFriendlyNameFor_v120>Windows Phone Silverlight 8.1 (v120)</_PlatformToolsetFriendlyNameFor_v120>
<_PlatformToolsetShortNameFor_v120>Windows Phone Silverlight 8.1</_PlatformToolsetShortNameFor_v120>
</PropertyGroup>
<!-- Import After -->
<Import Condition="Exists('$(MSBuildThisFileDirectory)ImportAfter\Default')" Project="$(MSBuildThisFileDirectory)ImportAfter\Default\*.props" />
</Project>

View File

@@ -36,7 +36,7 @@ class TestHeuristcs < Minitest::Test
def test_detect_still_works_if_nothing_matches
blob = Linguist::FileBlob.new(File.join(samples_path, "Objective-C/hello.m"))
match = Language.detect(blob)
match = Linguist.detect(blob)
assert_equal Language["Objective-C"], match
end
@@ -189,6 +189,16 @@ class TestHeuristcs < Minitest::Test
})
end
# Candidate languages = ["SQL", "PLpgSQL", "SQLPL", "PLSQL"]
def test_sql_by_heuristics
assert_heuristics({
"SQL" => ["SQL/create_stuff.sql", "SQL/db.sql", "SQL/dual.sql"],
"PLpgSQL" => all_fixtures("PLpgSQL", "*.sql"),
"SQLPL" => ["SQLPL/trigger.sql"],
"PLSQL" => all_fixtures("PLSQL", "*.sql")
})
end
# Candidate languages = ["Perl", "Perl6"]
def test_t_perl_by_heuristics
assert_heuristics({

View File

@@ -28,7 +28,7 @@ class TestInstrumentation < Minitest::Test
def test_detection_instrumentation_with_binary_blob
binary_blob = fixture_blob("Binary/octocat.ai")
Language.detect(binary_blob)
Linguist.detect(binary_blob)
# Shouldn't instrument this (as it's binary)
assert_equal 0, Linguist.instrumenter.events.size
@@ -36,7 +36,7 @@ class TestInstrumentation < Minitest::Test
def test_modeline_instrumentation
blob = fixture_blob("Data/Modelines/ruby")
Language.detect(blob)
Linguist.detect(blob)
detect_event = Linguist.instrumenter.events.last
detect_event_payload = detect_event[:args].first