cpp-merge
Version:
Command line tool to produce single source file from multiple C/C++ files
106 lines • 4.73 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const os_1 = require("os");
const stringUtils_1 = require("../common/stringUtils");
const CppFileParser_1 = __importDefault(require("./CppFileParser"));
const errors_1 = require("./errors");
const utils_1 = require("./utils");
const headerFileExtensions = [".h", ".hpp"];
const sourceFileExtensions = [".c", ".cpp"];
class CppFileMerger {
constructor(params = {}) {
this.parser = new CppFileParser_1.default();
this.systemIncludes = new Set();
this.processedOnce = new Set();
this.workingDirectory = "";
this.includeDirectory = params.includeDirectory ? path_1.default.resolve(params.includeDirectory) : undefined;
this.sourceDirectory = params.sourceDirectory ? path_1.default.resolve(params.sourceDirectory) : undefined;
}
parse(filePath) {
this.systemIncludes.clear();
this.processedOnce.clear();
this.workingDirectory = path_1.default.dirname(filePath);
const content = this.parseFile(filePath);
const sourceFilesContent = this.parseSourceFiles();
const systemIncludesContent = Array.from(this.systemIncludes.values())
.sort((a, b) => a.localeCompare(b))
.map(file => `#include <${file}>`)
.join(os_1.EOL);
const finalContent = [
systemIncludesContent,
content,
sourceFilesContent
]
.filter(content => !!content)
.join(os_1.EOL);
return (0, stringUtils_1.removeDoubleEmptyLines)(finalContent);
}
parseFile(filePath) {
if (this.processedOnce.has(filePath)) {
return "";
}
const fileContent = (0, utils_1.readFile)(filePath);
const result = this.parser.parse(fileContent);
result.systemIncludes.forEach(include => this.systemIncludes.add(include));
if (result.processOnce) {
this.processedOnce.add(filePath);
}
const currentDirectory = path_1.default.dirname(filePath);
const localIncludesContent = result.localIncludes.map(includeFilePath => {
return this.parseIncludedFile(includeFilePath, currentDirectory, filePath);
});
return [
...localIncludesContent,
result.content
].join(os_1.EOL);
}
parseIncludedFile(filePath, currentDirectory, processedFilePath) {
const searchFilePaths = [currentDirectory];
if (this.includeDirectory) {
searchFilePaths.push(this.includeDirectory);
}
const foundFilePath = (0, utils_1.findFile)(filePath, searchFilePaths);
if (!foundFilePath) {
throw new errors_1.IncludeFileNotFoundError(processedFilePath, filePath);
}
return this.parseFile(foundFilePath);
}
parseSourceFiles() {
const contents = [];
const searchDirectories = [this.workingDirectory];
if (this.sourceDirectory) {
searchDirectories.push(this.sourceDirectory);
}
this.processedOnce.forEach(filePath => {
const relativeFilePath = this.getHeaderRelativePath(filePath);
const extension = path_1.default.extname(relativeFilePath);
if (!headerFileExtensions.find(headerFileExtension => headerFileExtension === extension)) {
return;
}
const relativeFilePathWithoutExtension = relativeFilePath.substr(0, relativeFilePath.length - extension.length);
for (const sourceFileExtension of sourceFileExtensions) {
const sourceFileName = `${relativeFilePathWithoutExtension}${sourceFileExtension}`;
const foundFilePath = (0, utils_1.findFile)(sourceFileName, searchDirectories);
if (!foundFilePath) {
continue;
}
const sourceFileContent = this.parseFile(foundFilePath);
if (sourceFileContent) {
contents.push(sourceFileContent);
}
}
});
return contents.join(os_1.EOL);
}
getHeaderRelativePath(filePath) {
const fileDirectory = path_1.default.dirname(filePath);
const baseDirectory = this.includeDirectory && fileDirectory.startsWith(this.includeDirectory) ? this.includeDirectory : this.workingDirectory;
return path_1.default.relative(baseDirectory, filePath);
}
}
exports.default = CppFileMerger;
//# sourceMappingURL=CppFileMerger.js.map