@@ -95,6 +95,7 @@ define(function (require, exports, module) {
9595 _pendingLanguages = { } ,
9696 _languages = { } ,
9797 _fileExtensionToLanguageMap = { } ,
98+ _fileNameToLanguageMap = { } ,
9899 _modeToLanguageMap = { } ,
99100 _ready ;
100101
@@ -178,16 +179,19 @@ define(function (require, exports, module) {
178179 }
179180
180181 /**
181- * Resolves a file extension to a Language object.
182- * @param {!string } path Path to or extension of the file to find a language for
182+ * Resolves a file path to a Language object.
183+ * @param {!string } path Path to the file to find a language for
183184 * @return {Language } The language for the provided file type or the fallback language
184185 */
185- function getLanguageForFileExtension ( path ) {
186+ function getLanguageForPath ( path ) {
186187 var extension = _normalizeFileExtension ( PathUtils . filenameExtension ( path ) ) ,
187- language = _fileExtensionToLanguageMap [ extension ] ;
188+ filename = PathUtils . filename ( path ) ,
189+ language = extension ? _fileExtensionToLanguageMap [ extension ]
190+ : _fileNameToLanguageMap [ filename ] ;
188191
189192 if ( ! language ) {
190- console . log ( "Called LanguageManager.getLanguageForFileExtension with an unhandled file extension:" , extension ) ;
193+ extension ? console . log ( "Called LanguageManager.getLanguageForPath with an unhandled file extension:" , extension )
194+ : console . log ( "Called LanguageManager.getLanguageForPath with an unhandled file name:" , filename ) ;
191195 }
192196
193197 return language || _fallbackLanguage ;
@@ -233,6 +237,7 @@ define(function (require, exports, module) {
233237 this . _name = name ;
234238
235239 this . _fileExtensions = [ ] ;
240+ this . _fileNames = [ ] ;
236241 this . _modeToLanguageMap = { } ;
237242 }
238243
@@ -249,6 +254,9 @@ define(function (require, exports, module) {
249254 /** @type {Array.<string> } File extensions that use this language */
250255 Language . prototype . _fileExtensions = null ;
251256
257+ /** @type {Array.<string> } File names for extensionless files that use this language */
258+ Language . prototype . _fileNames = null ;
259+
252260 /** @type {{ prefix: string } } Line comment syntax */
253261 Language . prototype . _lineCommentSyntax = null ;
254262
@@ -351,6 +359,15 @@ define(function (require, exports, module) {
351359 // Use concat to create a copy of this array, preventing external modification
352360 return this . _fileExtensions . concat ( ) ;
353361 } ;
362+
363+ /**
364+ * Returns an array of file names for extensionless files that use this language.
365+ * @return {Array.<string> } Extensionless file names used by this language
366+ */
367+ Language . prototype . getFileNames = function ( ) {
368+ // Use concat to create a copy of this array, preventing external modification
369+ return this . _fileNames . concat ( ) ;
370+ } ;
354371
355372 /**
356373 * Adds a file extension to this language.
@@ -379,6 +396,31 @@ define(function (require, exports, module) {
379396 }
380397 } ;
381398
399+ /**
400+ * Adds a file name to the language which is used to match files that don't have extensions like "Makefile" for example.
401+ * Private for now since dependent code would need to by kept in sync with such changes.
402+ * See https://github.com/adobe/brackets/issues/2966 for plans to make this public.
403+ * @param {!string } extension An extensionless file name used by this language
404+ * @private
405+ */
406+ Language . prototype . _addFileName = function ( name ) {
407+ if ( this . _fileNames . indexOf ( name ) === - 1 ) {
408+ this . _fileNames . push ( name ) ;
409+
410+ var language = _fileNameToLanguageMap [ name ] ;
411+ if ( language ) {
412+ console . warn ( "Cannot register file name \"" + name + "\" for " + this . _name + ", it already belongs to " + language . _name ) ;
413+ } else {
414+ _fileNameToLanguageMap [ name ] = this ;
415+
416+ // TODO (issue #2966) Allow extensions to add new file names to existing languages
417+ // Notify on the Language and on LanguageManager?
418+ // $(this).triggerHandler("fileNameAdded", [name]);
419+ // $(exports).triggerHandler("fileNameAdded", [name, this]);
420+ }
421+ }
422+ } ;
423+
382424 /**
383425 * Returns whether the line comment syntax is defined for this language.
384426 * @return {boolean } Whether line comments are supported
@@ -504,6 +546,8 @@ define(function (require, exports, module) {
504546
505547 var language = new Language ( id , definition . name ) ,
506548 fileExtensions = definition . fileExtensions ,
549+ fileNames = definition . fileNames ,
550+ l ,
507551 i ;
508552
509553 var blockComment = definition . blockComment ;
@@ -522,10 +566,17 @@ define(function (require, exports, module) {
522566 language . _loadAndSetMode ( definition . mode ) . done ( function ( ) {
523567 // register language file extensions after mode has loaded
524568 if ( fileExtensions ) {
525- for ( i = 0 ; i < fileExtensions . length ; i ++ ) {
569+ for ( i = 0 , l = fileExtensions . length ; i < l ; i ++ ) {
526570 language . _addFileExtension ( fileExtensions [ i ] ) ;
527571 }
528572 }
573+
574+ // register language file names after mode has loaded
575+ if ( fileNames ) {
576+ for ( i = 0 , l = fileNames . length ; i < l ; i ++ ) {
577+ language . _addFileName ( fileNames [ i ] ) ;
578+ }
579+ }
529580
530581 // globally associate mode to language
531582 _setLanguageForMode ( language . getMode ( ) , language ) ;
@@ -581,8 +632,8 @@ define(function (require, exports, module) {
581632 } ) ;
582633
583634 // Public methods
584- exports . ready = _ready ;
585- exports . defineLanguage = defineLanguage ;
586- exports . getLanguage = getLanguage ;
587- exports . getLanguageForFileExtension = getLanguageForFileExtension ;
635+ exports . ready = _ready ;
636+ exports . defineLanguage = defineLanguage ;
637+ exports . getLanguage = getLanguage ;
638+ exports . getLanguageForPath = getLanguageForPath ;
588639} ) ;
0 commit comments