UNPKG

atom-nuclide

Version:

A unified developer experience for web and mobile development, built as a suite of features on top of Atom to provide hackability and the support of an active community.

114 lines (98 loc) 4.66 kB
Object.defineProperty(exports, '__esModule', { value: true }); exports.isHeaderFile = isHeaderFile; exports.isSourceFile = isSourceFile; exports.findIncludingSourceFile = findIncludingSourceFile; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } /* * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the license found in the LICENSE file in * the root directory of this source tree. */ var _escapeStringRegexp2; function _escapeStringRegexp() { return _escapeStringRegexp2 = _interopRequireDefault(require('escape-string-regexp')); } var _commonsNodeNuclideUri2; function _commonsNodeNuclideUri() { return _commonsNodeNuclideUri2 = _interopRequireDefault(require('../../commons-node/nuclideUri')); } var _rxjsBundlesRxUmdMinJs2; function _rxjsBundlesRxUmdMinJs() { return _rxjsBundlesRxUmdMinJs2 = require('rxjs/bundles/Rx.umd.min.js'); } var _commonsNodeProcess2; function _commonsNodeProcess() { return _commonsNodeProcess2 = require('../../commons-node/process'); } var HEADER_EXTENSIONS = new Set(['.h', '.hh', '.hpp', '.hxx', '.h++']); var SOURCE_EXTENSIONS = new Set(['.c', '.cc', '.cpp', '.cxx', '.c++', '.m', '.mm']); function isHeaderFile(filename) { return HEADER_EXTENSIONS.has((_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.extname(filename)); } function isSourceFile(filename) { return SOURCE_EXTENSIONS.has((_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.extname(filename)); } function processGrepResult(result, headerFile, includeRegex) { var splitIndex = result.indexOf('\0'); if (splitIndex === -1) { return null; } var filename = result.substr(0, splitIndex); if (!isSourceFile(filename)) { return null; } var match = includeRegex.exec(result.substr(splitIndex + 1)); if (match == null) { return null; } // Source-relative includes have to be verified. // Relative paths will match the (../)* rule (at index 2). if (match[2] != null) { var includePath = (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.normalize((_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.join((_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.dirname(filename), match[1])); if (includePath !== headerFile) { return null; } } return filename; } /** * Search all subdirectories of the header file for a source file that includes it. * We handle the two most common types of include statements: * * 1) Includes relative to the project root (if supplied); e.g. #include <a/b.h> * 2) Includes relative to the source file; e.g. #include "../../a.h" * * Note that we use an Observable here to enable cancellation. * The resulting Observable fires and completes as soon as a matching file is found; * 'null' will always be emitted if no results are found. */ function findIncludingSourceFile(headerFile, projectRoot) { var basename = (0, (_escapeStringRegexp2 || _escapeStringRegexp()).default)((_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.basename(headerFile)); var relativePath = (0, (_escapeStringRegexp2 || _escapeStringRegexp()).default)((_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.relative(projectRoot, headerFile)); var pattern = '^\\s*#include\\s+["<](' + relativePath + '|(../)*' + basename + ')[">]\\s*$'; var regex = new RegExp(pattern); var spawnGrepProcess = function spawnGrepProcess() { // We need both the file and the match to verify relative includes. // Relative includes may not always be correct, so we may have to go through all the results. return (0, (_commonsNodeProcess2 || _commonsNodeProcess()).safeSpawn)('grep', ['-RE', // recursive, extended '--null', // separate file/match with \0 pattern, (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.dirname(headerFile)]); }; return (0, (_commonsNodeProcess2 || _commonsNodeProcess()).observeProcess)(spawnGrepProcess).flatMap(function (message) { switch (message.kind) { case 'stdout': var file = processGrepResult(message.data, headerFile, regex); return file == null ? (_rxjsBundlesRxUmdMinJs2 || _rxjsBundlesRxUmdMinJs()).Observable.empty() : (_rxjsBundlesRxUmdMinJs2 || _rxjsBundlesRxUmdMinJs()).Observable.of(file); case 'error': throw new Error(message.error); case 'exit': return (_rxjsBundlesRxUmdMinJs2 || _rxjsBundlesRxUmdMinJs()).Observable.of(null); default: return (_rxjsBundlesRxUmdMinJs2 || _rxjsBundlesRxUmdMinJs()).Observable.empty(); } }).take(1); }