mirror of
https://github.com/KevinMidboe/linguist.git
synced 2025-10-28 17:20:22 +00:00
Strategies take result from previous strategy into account (#4099)
Each strategy takes as candidates the language outputted by the previous strategy if any. This was already the case for the Classifier and Heuristic strategies as these couldn't generate new candidate languages (as opposed to the Modeline, Filename, Shebang, and Extension strategies). In practice, this signifies that if, for example, the Shebang strategy finds two possible languages for a given file (as is currently possible with the perl interpreter), the next strategy, the Extension strategy, will use this information and further reduce the set of possible language. Currently, without this commit, the Extension strategy would discard the results from the previous strategy and start anew, possibly returning a different language from those returned by the Shebang strategy.
This commit is contained in:
@@ -3,17 +3,20 @@ module Linguist
|
||||
# Public: Use shebang to detect language of the blob.
|
||||
#
|
||||
# blob - An object that quacks like a blob.
|
||||
# candidates - A list of candidate languages.
|
||||
#
|
||||
# Examples
|
||||
#
|
||||
# Shebang.call(FileBlob.new("path/to/file"))
|
||||
#
|
||||
# Returns an Array with one Language if the blob has a shebang with a valid
|
||||
# interpreter, or empty if there is no shebang.
|
||||
def self.call(blob, _ = nil)
|
||||
# Returns an array of languages from the candidate list for which the
|
||||
# blob's shebang is valid. Returns an empty list if there is no shebang.
|
||||
# If the candidate list is empty, any language is a valid candidate.
|
||||
def self.call(blob, candidates)
|
||||
return [] if blob.symlink?
|
||||
|
||||
Language.find_by_interpreter interpreter(blob.data)
|
||||
languages = Language.find_by_interpreter interpreter(blob.data)
|
||||
candidates.any? ? candidates & languages : languages
|
||||
end
|
||||
|
||||
# Public: Get the interpreter from the shebang
|
||||
|
||||
@@ -2,8 +2,21 @@ module Linguist
|
||||
module Strategy
|
||||
# Detects language based on extension
|
||||
class Extension
|
||||
def self.call(blob, _)
|
||||
Language.find_by_extension(blob.name.to_s)
|
||||
# Public: Use the file extension to detect the blob's language.
|
||||
#
|
||||
# blob - An object that quacks like a blob.
|
||||
# candidates - A list of candidate languages.
|
||||
#
|
||||
# Examples
|
||||
#
|
||||
# Extension.call(FileBlob.new("path/to/file"))
|
||||
#
|
||||
# Returns an array of languages associated with a blob's file extension.
|
||||
# Selected languages must be in the candidate list, except if it's empty,
|
||||
# in which case any language is a valid candidate.
|
||||
def self.call(blob, candidates)
|
||||
languages = Language.find_by_extension(blob.name.to_s)
|
||||
candidates.any? ? candidates & languages : languages
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,9 +2,22 @@ module Linguist
|
||||
module Strategy
|
||||
# Detects language based on filename
|
||||
class Filename
|
||||
def self.call(blob, _)
|
||||
# Public: Use the filename to detect the blob's language.
|
||||
#
|
||||
# blob - An object that quacks like a blob.
|
||||
# candidates - A list of candidate languages.
|
||||
#
|
||||
# Examples
|
||||
#
|
||||
# Filename.call(FileBlob.new("path/to/file"))
|
||||
#
|
||||
# Returns an array of languages with a associated blob's filename.
|
||||
# Selected languages must be in the candidate list, except if it's empty,
|
||||
# in which case any language is a valid candidate.
|
||||
def self.call(blob, candidates)
|
||||
name = blob.name.to_s
|
||||
Language.find_by_filename(name)
|
||||
languages = Language.find_by_filename(name)
|
||||
candidates.any? ? candidates & languages : languages
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
51
test/fixtures/Perl/01-methods.pl
vendored
Normal file
51
test/fixtures/Perl/01-methods.pl
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
#!perl
|
||||
use Test::More;
|
||||
use Test::Exception;
|
||||
|
||||
use_ok 'Music::ScaleNote';
|
||||
|
||||
my $msn = Music::ScaleNote->new(
|
||||
scale_note => 'C',
|
||||
scale_name => 'pminor',
|
||||
# verbose => 1,
|
||||
);
|
||||
isa_ok $msn, 'Music::ScaleNote';
|
||||
|
||||
my $x;
|
||||
|
||||
throws_ok { $x = $msn->get_offset() }
|
||||
qr/note_name, note_format or offset not provided/, 'invalid get_offset';
|
||||
|
||||
my $format = 'midinum';
|
||||
$x = $msn->get_offset(
|
||||
note_name => 60,
|
||||
note_format => $format,
|
||||
offset => 1,
|
||||
);
|
||||
is $x->format($format), 63, 'get_offset';
|
||||
|
||||
$format = 'ISO';
|
||||
$x = $msn->get_offset(
|
||||
note_name => 'D#4',
|
||||
note_format => $format,
|
||||
offset => -1,
|
||||
);
|
||||
is $x->format($format), 'C4', 'get_offset';
|
||||
|
||||
throws_ok {
|
||||
$x = $msn->get_offset(
|
||||
note_name => 'C0',
|
||||
note_format => $format,
|
||||
offset => -1,
|
||||
)
|
||||
} qr/Octave: -1 out of bounds/, 'out of bounds';
|
||||
|
||||
throws_ok {
|
||||
$x = $msn->get_offset(
|
||||
note_name => 'A#127',
|
||||
note_format => $format,
|
||||
offset => 1,
|
||||
)
|
||||
} qr/Octave: 128 out of bounds/, 'out of bounds';
|
||||
|
||||
done_testing();
|
||||
Reference in New Issue
Block a user