mirror of
https://github.com/github/codeql-action.git
synced 2025-12-27 17:50:07 +08:00
170 lines
5.9 KiB
JavaScript
170 lines
5.9 KiB
JavaScript
"use strict";
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Languages = void 0;
|
|
const languages_json_1 = __importDefault(require("language-map/languages.json"));
|
|
const utils_1 = require("./utils");
|
|
/**
|
|
* The extension map can contain multiple languages with the same extension,
|
|
* but we only want a single one. For the moment, these clashes are resolved
|
|
* by the simple heuristic below listing high-priority languages. We may want
|
|
* to consider smarter heuristics to correctly identify languages in cases
|
|
* where the extension is ambiguous. The ordering of the list matters and
|
|
* languages earlier on will get a higher priority when resolving clashes.
|
|
*/
|
|
const importantLanguages = [
|
|
'javascript',
|
|
'typescript',
|
|
'ruby',
|
|
'python',
|
|
'java',
|
|
'c',
|
|
'c++',
|
|
'c#',
|
|
'rust',
|
|
'scala',
|
|
'perl',
|
|
'go',
|
|
];
|
|
const ALL_REGEXES = {
|
|
c: {
|
|
// matches when // are the first two characters of a line
|
|
singleLineComment: /^\/\//,
|
|
// matches when /* exists in a line
|
|
multiLineCommentOpen: /\/\*/,
|
|
// matches when /* starts a line
|
|
multiLineCommentOpenStart: /^\/\*/,
|
|
// matches when */ exists a line
|
|
multiLineCommentClose: /\*\//,
|
|
// matches when */ ends a line
|
|
multiLineCommentCloseEnd: /\*\/$/,
|
|
// matches /* ... */
|
|
multiLineCommentOpenAndClose: /\/\*.*\*\//,
|
|
},
|
|
python: {
|
|
// matches when # the first character of a line
|
|
singleLineComment: /^#/,
|
|
},
|
|
ruby: {
|
|
// matches when # the first character of a line
|
|
singleLineComment: /^#/,
|
|
// For ruby multiline comments, =begin and =end must be
|
|
// on their own lines
|
|
// matches when =begin starts a line
|
|
multiLineCommentOpen: /^=begin/,
|
|
// matches when "begin starts a line
|
|
multiLineCommentOpenStart: /^=begin/,
|
|
// matches when "end ends a line
|
|
multiLineCommentClose: /^=end/,
|
|
// matches when "end ends a line
|
|
multiLineCommentCloseEnd: /^=end$/,
|
|
// not possible in ruby
|
|
multiLineCommentOpenAndClose: /^\0$/,
|
|
},
|
|
html: {
|
|
// There is no single line comment
|
|
singleLineComment: /^\0$/,
|
|
// matches when =begin starts a line
|
|
multiLineCommentOpen: /<!--/,
|
|
// matches when "begin starts a line
|
|
multiLineCommentOpenStart: /^<!--/,
|
|
// matches when "end ends a line
|
|
multiLineCommentClose: /-->/,
|
|
// matches when "end ends a line
|
|
multiLineCommentCloseEnd: /-->$/,
|
|
// matches <!-- ... -->
|
|
multiLineCommentOpenAndClose: /<!--.*-->/,
|
|
},
|
|
};
|
|
/**
|
|
* detecte program language through file extension
|
|
*
|
|
* @export
|
|
* @class LanguageDetector
|
|
*/
|
|
class Languages {
|
|
/**
|
|
* Creates an instance of Detector.
|
|
*/
|
|
constructor() {
|
|
Object.defineProperty(this, "extensionMap", {
|
|
enumerable: true,
|
|
configurable: true,
|
|
writable: true,
|
|
value: {}
|
|
});
|
|
/**
|
|
* load language before detecting
|
|
*/
|
|
Object.defineProperty(this, "loadExtensionMap", {
|
|
enumerable: true,
|
|
configurable: true,
|
|
writable: true,
|
|
value: () => {
|
|
const extensions = {};
|
|
Object.keys(languages_json_1.default).forEach((language) => {
|
|
const languageMode = languages_json_1.default[language];
|
|
const languageExtensions = (languageMode && languageMode.extensions) || [];
|
|
languageExtensions.forEach((extension) => {
|
|
const lowerCaseExtension = extension.toLowerCase();
|
|
const lowerCaseLanguage = language.toLowerCase();
|
|
if (!extensions[lowerCaseExtension]) {
|
|
extensions[lowerCaseExtension] = lowerCaseLanguage;
|
|
}
|
|
else {
|
|
const currentLanguagePriority = importantLanguages.indexOf(extensions[lowerCaseExtension]);
|
|
if (currentLanguagePriority === -1) {
|
|
extensions[lowerCaseExtension] = lowerCaseLanguage;
|
|
}
|
|
else {
|
|
const otherPriority = importantLanguages.indexOf(lowerCaseLanguage);
|
|
if (otherPriority !== -1 && otherPriority < currentLanguagePriority)
|
|
extensions[lowerCaseExtension] = lowerCaseLanguage;
|
|
}
|
|
}
|
|
});
|
|
});
|
|
return { ...extensions, ...utils_1.ExtensionJustify };
|
|
}
|
|
});
|
|
this.extensionMap = this.loadExtensionMap();
|
|
}
|
|
/**
|
|
* Retrieve the regular expressions for a given language.
|
|
* This is incomplete, but covers most of the languages we
|
|
* see in the wild.
|
|
*
|
|
* @param language the language to retrieve regexes for
|
|
*/
|
|
getRegexes(language) {
|
|
switch (language) {
|
|
case 'html':
|
|
case 'xml':
|
|
return ALL_REGEXES.html;
|
|
case 'ruby':
|
|
return ALL_REGEXES.ruby;
|
|
case 'python':
|
|
return ALL_REGEXES.python;
|
|
default:
|
|
// not exact, but likely the best guess for any other unspecified language.
|
|
return ALL_REGEXES.c;
|
|
}
|
|
}
|
|
/**
|
|
* return extension map
|
|
*/
|
|
getExtensionMap() {
|
|
return this.extensionMap;
|
|
}
|
|
/**
|
|
* get file type through a path
|
|
*/
|
|
getType(path) {
|
|
const fileExtension = `.${path.split('.').pop()}`;
|
|
return this.extensionMap[fileExtension] || '';
|
|
}
|
|
}
|
|
exports.Languages = Languages;
|
|
//# sourceMappingURL=languages.js.map
|