UNPKG

@nxrocks/common-jvm

Version:

Common library to share code among the JVM-related plugins.

374 lines (364 loc) 16.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SPOTLESS_GRADLE_PLUGIN_VERSION = exports.SPOTLESS_GRADLE_PLUGIN_ID = exports.GRADLE_PLUGIN_REGEX = exports.SPOTLESS_CONFIG_REGEX = exports.GRADLE_PLUGINS_REGEX = void 0; exports.getGradlePlugins = getGradlePlugins; exports.hasGradlePlugin = hasGradlePlugin; exports.getGradlePlugin = getGradlePlugin; exports.disableGradlePlugin = disableGradlePlugin; exports.addGradlePlugin = addGradlePlugin; exports.getGradleSpotlessConfig = getGradleSpotlessConfig; exports.applySpotlessGradlePlugin = applySpotlessGradlePlugin; exports.addSpotlessGradlePlugin = addSpotlessGradlePlugin; exports.hasMultiModuleGradleProjectInTree = hasMultiModuleGradleProjectInTree; exports.hasMultiModuleGradleProject = hasMultiModuleGradleProject; exports.checkForMultiModuleGradleProject = checkForMultiModuleGradleProject; exports.hasGradleModuleInTree = hasGradleModuleInTree; exports.hasGradleModule = hasGradleModule; exports.getGradleModules = getGradleModules; exports.addGradleModule = addGradleModule; exports.initGradleParentModule = initGradleParentModule; exports.getGradleWrapperFiles = getGradleWrapperFiles; exports.hasGradleWrapperInTree = hasGradleWrapperInTree; exports.hasGradleWrapper = hasGradleWrapper; exports.getCoordinatesForGradleProjet = getCoordinatesForGradleProjet; const utils_1 = require("./utils"); const fileutils_1 = require("@nx/workspace/src/utilities/fileutils"); const path_1 = require("path"); const common_1 = require("@nxrocks/common"); exports.GRADLE_PLUGINS_REGEX = /(?:plugins\s*\{\s*)([^}]+)(?:\s*\})/g; exports.SPOTLESS_CONFIG_REGEX = /(?:(spotless|configure<com.diffplug.gradle.spotless.SpotlessExtension>)\s*\{\s*)([^}]+)(?:\s*\})/g; exports.GRADLE_PLUGIN_REGEX = /\s*(id|java|kotlin)(?:\s*\(?\s*['"]([^'"]+)['"]\s*\)?\s*(?:version\s+['"]([^'"]+)['"])?\s*(?:apply\s+(true|false))?)?/g; exports.SPOTLESS_GRADLE_PLUGIN_ID = 'com.diffplug.spotless'; exports.SPOTLESS_GRADLE_PLUGIN_VERSION = '6.8.0'; function getGradlePlugins(content) { const plugins = []; const pluginsContent = new RegExp(exports.GRADLE_PLUGINS_REGEX).exec(content)?.[1]; if (pluginsContent) { const pluginRegExp = new RegExp(exports.GRADLE_PLUGIN_REGEX); let pluginMatches = pluginRegExp.exec(pluginsContent); while (pluginMatches) { const id = pluginMatches[2]; const version = pluginMatches[3]; const applied = pluginMatches[4] ? pluginMatches[4] === 'true' : true; const kotlin = pluginMatches[1] === 'kotlin'; const java = pluginMatches[1] === 'java'; plugins.push({ id, version, kotlin, java, applied }); pluginMatches = pluginRegExp.exec(pluginsContent); } } return plugins; } function hasGradlePlugin(content, pluginId, pluginVersion) { const plugins = getGradlePlugins(content); return plugins.some((plugin) => plugin.id === pluginId && (!pluginVersion || plugin.version === pluginVersion)); } function getGradlePlugin(content, pluginId) { const plugins = getGradlePlugins(content); return plugins.find((plugin) => plugin.id === pluginId); } function disableGradlePlugin(tree, rootFolder, language, pluginId, withKotlinDSL = language === 'kotlin') { const ext = withKotlinDSL ? '.gradle.kts' : '.gradle'; const buildGradle = tree.read(`${rootFolder}/build${ext}`, 'utf-8'); if (buildGradle === null) return false; const plugin = getGradlePlugin(buildGradle, pluginId); if (plugin && plugin.applied) { const newBuildGradle = buildGradle.replace(exports.GRADLE_PLUGINS_REGEX, (_match, content) => { const newContent = content.replace(exports.GRADLE_PLUGIN_REGEX, (pluginMatch, _, id) => { if (id === pluginId) { const lastQuoteIdx = pluginMatch.lastIndexOf(withKotlinDSL ? '"' : "'"); const disabledPlugin = `${pluginMatch.substring(0, lastQuoteIdx + 1)} apply false${pluginMatch.substring(lastQuoteIdx + 1)}`; return disabledPlugin; } return pluginMatch; }); return `plugins {\n\t${newContent}}`; }); tree.write(`${rootFolder}/build${ext}`, newBuildGradle); return true; } return false; } function addGradlePlugin(tree, rootFolder, language, pluginId, pluginVersion, withKotlinDSL = language === 'kotlin') { const ext = withKotlinDSL ? '.gradle.kts' : '.gradle'; const buildGradle = tree.read(`${rootFolder}/build${ext}`, 'utf-8'); if (buildGradle === null) return false; let withVersion = ''; if (pluginVersion) { withVersion = withKotlinDSL ? ` version "${pluginVersion}"` : ` version '${pluginVersion}'`; } const pluginToAdd = withKotlinDSL ? `id("${pluginId}")${withVersion}` : `id '${pluginId}'${withVersion}`; if (!hasGradlePlugin(buildGradle, pluginId)) { if (!exports.GRADLE_PLUGINS_REGEX.test(buildGradle)) { const plugins = `plugins {\n\t${pluginToAdd}\n}\n`; tree.write(`${rootFolder}/build${ext}`, plugins + buildGradle); } else { const newBuildGradle = buildGradle.replace(exports.GRADLE_PLUGINS_REGEX, (match, content) => { return `plugins {\n\t${content}\t${pluginToAdd}\n}`; }); tree.write(`${rootFolder}/build${ext}`, newBuildGradle); } return true; } return false; } function getGradleSpotlessBaseConfig(language, languageConfig, baseGitBranch, withKotlinDSL = language === 'kotlin') { const ratchetFrom = baseGitBranch ? `// optional: limit format enforcement to just the files changed by this feature branch ratchetFrom${withKotlinDSL ? `("${baseGitBranch}")` : ` '${baseGitBranch}'`} ` : ''; return ` ${withKotlinDSL ? 'configure<com.diffplug.gradle.spotless.SpotlessExtension>' : 'spotless'} { ${ratchetFrom} format${withKotlinDSL ? '("misc")' : " 'misc',"} { // define the files to apply 'misc' to target${withKotlinDSL ? '("*.gradle.kts", "*.md", ".gitignore")' : " '*.gradle', '*.md', '.gitignore'"} // define the steps to apply to those files trimTrailingWhitespace() indentWithTabs() // or spaces. Takes an integer argument if you don't like 4 endWithNewline() } ${languageConfig} } `; } function getGradleSpotlessConfig(language, jdkVersion, baseGitBranch, withKotlinDSL = language === 'kotlin') { switch (language) { case 'java': return getGradleSpotlessBaseConfig(language, ` java {// to customize, go to https://github.com/diffplug/spotless/tree/main/plugin-gradle#java target${withKotlinDSL ? '("src/*/java/**/*.java")' : " 'src/*/java/**/*.java'"} // Use the default importOrder configuration importOrder() // Clean up removeUnusedImports() // Apply google-java-format formatter googleJavaFormat() }`, baseGitBranch, withKotlinDSL); case 'kotlin': return getGradleSpotlessBaseConfig(language, ` kotlin { // to customize, go to https://github.com/diffplug/spotless/tree/main/plugin-gradle#kotlin ${jdkVersion && jdkVersion >= 11 ? '// Apply ktfmt formatter(similar to google-java-format, but for Kotlin)' : '// Apply ktlint formatter'} ${jdkVersion && jdkVersion >= 11 ? 'ktfmt()' : 'ktlint()'} } kotlinGradle { target${withKotlinDSL ? '("*.gradle.kts")' : " '*.gradle.kts'"} // default target for kotlinGradle ${jdkVersion && jdkVersion >= 11 ? 'ktfmt()' : 'ktlint()'} }`, baseGitBranch, withKotlinDSL); case 'groovy': return getGradleSpotlessBaseConfig(language, ` groovy {// to customize, go to https://github.com/diffplug/spotless/tree/main/plugin-gradle#groovy // Use the default importOrder configuration importOrder() // Clean up removeUnusedImports() // Apply groovy-eclipse formatter greclipse() } groovyGradle { target${withKotlinDSL ? '("*.gradle")' : " '*.gradle'"} // default target of groovyGradle greclipse() }`, baseGitBranch, withKotlinDSL); } } function applySpotlessGradlePlugin(tree, rootFolder, language, jdkVersion, gitBaseBranch, withKotlinDSL = language === 'kotlin') { const ext = withKotlinDSL ? '.gradle.kts' : '.gradle'; const buildGradle = tree.read(`${rootFolder}/build${ext}`, 'utf-8'); if (buildGradle === null) return false; if (!exports.SPOTLESS_CONFIG_REGEX.test(buildGradle)) { const spotlessConfig = getGradleSpotlessConfig(language, jdkVersion, gitBaseBranch, withKotlinDSL); tree.write(`${rootFolder}/build${ext}`, buildGradle + spotlessConfig); return true; } return false; } function addSpotlessGradlePlugin(tree, rootFolder, language, jdkVersion, gitBaseBranch, withKotlinDSL = language === 'kotlin') { const added = addGradlePlugin(tree, rootFolder, language, exports.SPOTLESS_GRADLE_PLUGIN_ID, exports.SPOTLESS_GRADLE_PLUGIN_VERSION, withKotlinDSL); if (added) { applySpotlessGradlePlugin(tree, rootFolder, language, jdkVersion, gitBaseBranch, withKotlinDSL); } return added; } function hasMultiModuleGradleProjectInTree(tree, rootFolder) { if (!(0, utils_1.isGradleProjectSettingsInTree)(tree, rootFolder)) return false; const extension = (0, utils_1.getGradleBuildFilesExtensionInTree)(tree, rootFolder); const settings = tree.read(`./${rootFolder}/settings${extension}`, 'utf-8'); if (settings === null) return false; return checkForMultiModuleGradleProject(settings); } function hasMultiModuleGradleProject(cwd) { if (!(0, utils_1.hasGradleSettingsFile)(cwd)) return false; const extension = (0, utils_1.getGradleBuildFilesExtension)({ root: cwd }); const settings = (0, common_1.getProjectFileContent)({ root: cwd }, `settings${extension}`); return checkForMultiModuleGradleProject(settings); } function checkForMultiModuleGradleProject(settings) { const opts = { fragments: [/rootProject\.name\s*=\s*'/, /include\s+'/], logicalOp: 'and', }; const optsKts = { fragments: [/rootProject\.name\s*=\s*"/, /include\s*\("/], logicalOp: 'and', }; return ((0, utils_1.checkProjectFileContains)(settings, opts) || (0, utils_1.checkProjectFileContains)(settings, optsKts)); } function hasGradleModuleInTree(tree, rootFolder, moduleName) { if (!hasMultiModuleGradleProjectInTree(tree, rootFolder)) return false; const ext = (0, utils_1.getGradleBuildFilesExtensionInTree)(tree, rootFolder); const settings = tree.read(`./${rootFolder}/settings${ext}`, 'utf-8'); if (settings === null) return false; return checkForModule(settings, moduleName); } function hasGradleModule(cwd, moduleName) { if (!hasMultiModuleGradleProject(cwd)) return false; const extension = (0, utils_1.getGradleBuildFilesExtension)({ root: cwd }); const settings = (0, common_1.getProjectFileContent)({ root: cwd }, `settings${extension}`); return checkForModule(settings, moduleName); } function checkForModule(settings, moduleName) { const opts = { fragments: [ new RegExp(`rootProject\\.name\\s*=\\s*'`), new RegExp(`include\\s+':?(?:[^:]*:)*${moduleName}'`), ], logicalOp: 'and', }; const optsKts = { fragments: [ new RegExp(`rootProject\\.name\\s*=\\s*"`), new RegExp(`include\\(":?(?:[^:]*:)*${moduleName}"\\)`), ], logicalOp: 'and', }; return ((0, utils_1.checkProjectFileContains)(settings, opts) || (0, utils_1.checkProjectFileContains)(settings, optsKts)); } function getGradleModules(cwd) { if (!hasMultiModuleGradleProject(cwd)) return []; const extension = (0, utils_1.getGradleBuildFilesExtension)({ root: cwd }); const settings = (0, common_1.getProjectFileContent)({ root: cwd }, `settings${extension}`); const modulesRegex = extension === '.gradle.kts' ? /include\s*\("([\w:]+)"\)/g : /include\s+'([\w:]+)'/g; const modules = []; let m; while ((m = modulesRegex.exec(settings))) { modules.push(m?.[1]); } return modules; } function addGradleModule(tree, rootFolder, moduleName, offsetFromRoot, withKotlinDSL) { if (hasGradleModuleInTree(tree, rootFolder, moduleName)) return false; const ext = withKotlinDSL ? '.gradle.kts' : '.gradle'; const settingsGradle = tree.read(`${rootFolder}/settings${ext}`, 'utf-8'); if (settingsGradle === null) return false; let lastIncludeIdx = settingsGradle.lastIndexOf('include'); lastIncludeIdx = lastIncludeIdx > 0 ? lastIncludeIdx : settingsGradle.length; const name = offsetFromRoot === '.' ? moduleName : `${offsetFromRoot}/${moduleName}`.replaceAll('/', ':'); const newModule = withKotlinDSL ? `\ninclude("${name}")\n` : `\ninclude '${name}'\n`; const newSettingGradle = settingsGradle.slice(0, lastIncludeIdx) + newModule + settingsGradle.slice(lastIncludeIdx); tree.write(`${rootFolder}/settings${ext}`, newSettingGradle); return true; } function initGradleParentModule(tree, rootFolder, groupId, parentModuleName, childModuleName, offsetFromRoot, withKotlinDSL, helpComment = '') { const name = offsetFromRoot === '.' ? childModuleName : `${offsetFromRoot}/${childModuleName}`.replaceAll('/', ':'); const settingsGradle = ` ${helpComment} rootProject.name = ${withKotlinDSL ? `"${parentModuleName}"` : `'${parentModuleName}'`} ${withKotlinDSL ? `include("${name}")` : `include '${name}'`} `; const buildGradle = `group = ${withKotlinDSL ? `"${groupId}"` : `'${groupId}'`}`; const ext = withKotlinDSL ? '.kts' : ''; tree.write(`./${rootFolder}/settings.gradle${ext}`, settingsGradle); tree.write(`./${rootFolder}/build.gradle${ext}`, buildGradle); } function getGradleWrapperFiles() { return [ 'gradlew', 'gradlew.bat', 'gradlew.cmd', 'gradle/wrapper/gradle-wrapper.jar', 'gradle/wrapper/gradle-wrapper.properties', ]; } function hasGradleWrapperInTree(tree, rootFolder) { return hasGradleWrapperWithPredicate((file) => tree.exists(`./${rootFolder}/${file}`)); } function hasGradleWrapper(rootFolder) { return hasGradleWrapperWithPredicate((file) => (0, fileutils_1.fileExists)((0, path_1.resolve)(rootFolder, file))); } function getCoordinatesForGradleProjet(cwd) { let groupId; let artifactId; const ext = (0, utils_1.getGradleBuildFilesExtension)({ root: cwd }); const { name } = (0, common_1.getNameAndRoot)(cwd); if ((0, utils_1.hasGradleSettingsFile)(cwd)) { const settingsGradle = (0, common_1.getProjectFileContent)({ root: cwd }, `settings${ext}`); artifactId = settingsGradle.match(/rootProject\.name\s*=\s*['"]([^"']+)['"]/)?.[1]; } artifactId = artifactId ?? name; // use the folder name as default if still undefined if ((0, utils_1.hasGradleBuildFile)(cwd)) { const buildGradle = (0, common_1.getProjectFileContent)({ root: cwd }, `build${ext}`); groupId = buildGradle.match(/group\s*=\s*['"]([^"']+)['"]/)?.[1]; } if (!groupId && ext && artifactId) { // groupId might be defined at parent module level, continue searching for it groupId = getGroupIdInHierarchy(cwd, ext); } return { groupId, artifactId }; } function getGroupIdInHierarchy(cwd, buildFileExtension) { const { root, name } = (0, common_1.getNameAndRoot)(cwd); if (root === '.') // we reach the root of the workspace without finding the groupId, so we stop the search return undefined; let groupId; if ((0, utils_1.hasGradleBuildFile)(root) && hasGradleModule(root, name)) { const buildGradle = (0, common_1.getProjectFileContent)({ root }, `build${buildFileExtension}`); groupId = buildGradle.match(/group\s*=\s*['"]([^"']+)['"]/)?.[1]; } return groupId ?? getGroupIdInHierarchy(root, buildFileExtension); } function hasGradleWrapperWithPredicate(predicate) { return ([ 'gradlew', 'gradle/wrapper/gradle-wrapper.jar', 'gradle/wrapper/gradle-wrapper.properties', ].every((file) => predicate(file)) && ['gradlew.bat', 'gradlew.cmd'].some((file) => predicate(file))); } //# sourceMappingURL=gradle-utils.js.map