Skip to content

Commit

Permalink
Merge pull request #387 from mshima/ktlint
Browse files Browse the repository at this point in the history
Add ktlint generator and ktlint format.
  • Loading branch information
DanielFran authored Jul 25, 2024
2 parents f1b61f7 + 29b0cf4 commit 59d6bde
Show file tree
Hide file tree
Showing 29 changed files with 557 additions and 114 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ insert_final_newline = true

# Change these settings to your own preference
indent_style = space
indent_size = 2
indent_size = 4

[*.md]
trim_trailing_whitespace = false
26 changes: 26 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#
# Copyright the original author or authors from the JHipster project.
#
# This file is part of the JHipster project, see https://www.jhipster.tech/
# for more information.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

version: 2
updates:
- package-ecosystem: 'gradle'
directory: '/generators/ktlint/resources/'
schedule:
interval: 'daily'
open-pull-requests-limit: 5
4 changes: 3 additions & 1 deletion .github/workflows/angular.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ jobs:
!contains(github.event.pull_request.title, '[ci skip]') &&
github.event.action != 'closed' &&
!contains(github.event.pull_request.labels.*.name, 'pr: skip-ci')
timeout-minutes: 25
# ktlint takes 8 minutes to run, add additional 15 minutes
# https://github.com/pinterest/ktlint/issues/2754
timeout-minutes: 40
strategy:
fail-fast: false
# Matrix available at https://github.com/jhipster/jhipster-kotlin/tree/main/test-integration/workflow-samples/
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/react.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ jobs:
!contains(github.event.pull_request.title, '[ci skip]') &&
github.event.action != 'closed' &&
!contains(github.event.pull_request.labels.*.name, 'pr: skip-ci')
timeout-minutes: 25
# ktlint takes 8 minutes to run, add additional 15 minutes
# https://github.com/pinterest/ktlint/issues/2754
timeout-minutes: 40
strategy:
fail-fast: false
# Matrix available at https://github.com/jhipster/jhipster-kotlin/tree/main/test-integration/workflow-samples/
Expand Down
5 changes: 1 addition & 4 deletions .prettierrc.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# Prettier configuration

printWidth: 140
singleQuote: true
tabWidth: 4
useTabs: false

# js and ts rules:
arrowParens: avoid
bracketSameLine: false
16 changes: 15 additions & 1 deletion .yo-rc.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
{
"generator-jhipster": {
"additionalSubGenerators": "",
"additionalSubGenerators": "ktlint,migration",
"baseName": "kotlin",
"cli": true,
"cliName": "khipster",
"entities": [],
"generators": {
"ktlint": {
"command": false,
"priorities": ["default"],
"sbs": null,
"written": true
},
"migration": {
"command": false,
"priorities": ["postWriting"],
"sbs": null,
"written": true
},
"spring-boot": {
"command": false,
"priorities": ["initializing", "composing"],
Expand All @@ -15,6 +27,8 @@
},
"jhipsterVersion": "8.5.0",
"localBlueprint": false,
"packageJsonType": "module",
"prettierTabWidth": 4,
"sampleWritten": true,
"subGenerators": ["spring-boot"]
}
Expand Down
72 changes: 72 additions & 0 deletions generators/ktlint/__snapshots__/generator.spec.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`SubGenerator kotlin of kotlin JHipster blueprint > gradle > should match source calls 1`] = `
{
"addGradlePluginToBuildScript": [
{
"group": "org.jlleitschuh.gradle",
"name": "ktlint-gradle",
"version": "'KTLINT-GRADLE-VERSION'",
},
],
}
`;

exports[`SubGenerator kotlin of kotlin JHipster blueprint > gradle > should succeed 1`] = `
{
".yo-rc.json": {
"stateCleared": "modified",
},
"package.json": {
"stateCleared": "modified",
},
}
`;

exports[`SubGenerator kotlin of kotlin JHipster blueprint > maven > should match source calls 1`] = `
{
"addJavaDefinition": [
{
"versions": [
{
"name": "ktlint-maven-plugin",
"version": "'KTLINT-MAVEN-VERSION'",
},
],
},
],
"addMavenDefinition": [
{
"plugins": [
{
"additionalContent": " <executions>
<execution>
<id>check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<failOnViolation>false</failOnViolation>
</configuration>
</execution>
</executions>",
"artifactId": "ktlint-maven-plugin",
"groupId": "com.github.gantsign.maven",
"version": "\${ktlint-maven-plugin.version}",
},
],
},
],
}
`;

exports[`SubGenerator kotlin of kotlin JHipster blueprint > maven > should succeed 1`] = `
{
".yo-rc.json": {
"stateCleared": "modified",
},
"package.json": {
"stateCleared": "modified",
},
}
`;
18 changes: 18 additions & 0 deletions generators/ktlint/command.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* @type {import('generator-jhipster').JHipsterCommandDefinition}
*/
const command = {
options: {},
configs: {
skipKtlintFormat: {
cli: {
desc: 'Skip ktlintFormat',
type: Boolean,
},
scope: 'generator',
},
},
arguments: {},
};

export default command;
147 changes: 147 additions & 0 deletions generators/ktlint/generator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import { createWriteStream, existsSync } from 'node:fs';
import { chmod, mkdir, rm } from 'node:fs/promises';
import { platform } from 'node:os';
import { join } from 'node:path';
import { pipeline } from 'node:stream/promises';
import BaseApplicationGenerator from 'generator-jhipster/generators/base-application';
import axios from 'axios';
import { createKtlintTransform, filterKtlintTransformFiles } from './internal/ktlint-transform.js';

export default class extends BaseApplicationGenerator {
ktlintFolder;
ktlintExecutable;

constructor(args, opts, features) {
super(args, opts, {
...features,
queueCommandTasks: true,
});
}

async beforeQueue() {
await this.dependsOnBootstrapApplicationServer();
}

get [BaseApplicationGenerator.LOADING]() {
return this.asLoadingTaskGroup({
async loading({ application }) {
this.loadJavaDependenciesFromGradleCatalog(application.javaDependencies);
this.ktlintFolder = this.destinationPath('.ktlint', application.javaDependencies['ktlint-cli']);
this.ktlintExecutable = join(this.ktlintFolder, platform() === 'win32' ? 'ktlint.bat' : 'ktlint');
},
});
}

get [BaseApplicationGenerator.DEFAULT]() {
return this.asDefaultTaskGroup({
async downloadKtlint({ application }) {
if (!this.options.skipKtlintFormat && !existsSync(this.ktlintExecutable)) {
await this.env.adapter.progress(
async () => {
try {
const ktlintVersion = application.javaDependencies['ktlint-cli'];
const ktlintUrl = 'https://github.com/pinterest/ktlint/releases/download/';

await mkdir(this.ktlintFolder, { recursive: true });

const response = await axios.get(`${ktlintUrl}${ktlintVersion}/ktlint`, { responseType: 'stream' });
const ktlintFile = join(this.ktlintFolder, 'ktlint');
await pipeline(response.data, createWriteStream(ktlintFile));
await chmod(ktlintFile, 0o755);

const batResponse = await axios.get(`${ktlintUrl}/${ktlintVersion}/ktlint.bat`, { responseType: 'stream' });
await pipeline(batResponse.data, createWriteStream(join(this.ktlintFolder, 'ktlint.bat')));
} catch (error) {
this.log.error('Failed to download ktlint');
await rm(this.ktlintFolder, { recursive: true });
throw error;
}
},
{ name: 'downloading ktlint' },
);
}
},
async defaultTemplateTask({ control }) {
if (!this.options.skipKtlintFormat) {
const destinationPath = this.destinationPath();
this.queueTransformStream(
{
name: 'formating using ktlint',
filter: file => filterKtlintTransformFiles(file) && file.path.startsWith(destinationPath),
refresh: false,
},
createKtlintTransform.call(this, {
ktlintExecutable: this.ktlintExecutable,
cwd: destinationPath,
ignoreErrors: control.ignoreNeedlesError,
}),
);
}
},
});
}

get [BaseApplicationGenerator.WRITING]() {
return this.asWritingTaskGroup({
async writing({ application }) {
await this.writeFiles({
blocks: [{ templates: ['.gitignore.jhi.ktlint'] }],
context: application,
});
},
});
}

get [BaseApplicationGenerator.POST_WRITING]() {
return this.asPostWritingTaskGroup({
async postWriting({ application }) {
const command = application.buildToolGradle ? './gradlew :ktlintFormat' : './mvnw ktlint:format';
this.packageJson.merge({
scripts: {
'ktlint:format': command,
},
});
},
addDependencies({ application, source }) {
if (application.buildToolGradle) {
source.addGradlePluginToBuildScript({
group: 'org.jlleitschuh.gradle',
name: 'ktlint-gradle',
version: application.javaDependencies['ktlint-gradle'],
});

/* JHipster 8 based configuration
source.addGradleDependencyCatalogPlugins([{ pluginName: 'ktlint', id: 'org.jlleitschuh.gradle.ktlint', version: KTLINT_GRADLE_VERSION, addToBuild: true }]);
*/
} else {
source.addJavaDefinition({
versions: [{ name: 'ktlint-maven-plugin', version: application.javaDependencies['ktlint-maven'] }],
});

const ktlintMavenOther = ` <executions>
<execution>
<id>check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<failOnViolation>false</failOnViolation>
</configuration>
</execution>
</executions>`;

source.addMavenDefinition({
plugins: [
{
groupId: 'com.github.gantsign.maven',
artifactId: 'ktlint-maven-plugin',
version: '${ktlint-maven-plugin.version}',
additionalContent: ktlintMavenOther,
},
],
});
}
},
});
}
}
33 changes: 33 additions & 0 deletions generators/ktlint/generator.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { beforeAll, describe, expect, it } from 'vitest';

import { fromMatrix, defaultHelpers as helpers, result } from 'generator-jhipster/testing';

const SUB_GENERATOR = 'ktlint';
const SUB_GENERATOR_NAMESPACE = `jhipster-kotlin:${SUB_GENERATOR}`;

describe('SubGenerator kotlin of kotlin JHipster blueprint', () => {
Object.entries(fromMatrix({ buildTool: ['maven', 'gradle'] })).forEach(([name, config]) => {
describe(name, () => {
beforeAll(async function () {
await helpers
.run(SUB_GENERATOR_NAMESPACE)
.withJHipsterConfig(config)
.withOptions({
ignoreNeedlesError: true,
skipKtlintFormat: true,
})
.withJHipsterLookup()
.withMockedSource()
.withParentBlueprintLookup(['generators', 'generators/*/generators']);
});

it('should succeed', () => {
expect(result.getStateSnapshot()).toMatchSnapshot();
});

it('should match source calls', () => {
expect(result.sourceCallsArg).toMatchSnapshot();
});
});
});
});
2 changes: 2 additions & 0 deletions generators/ktlint/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from './generator.js';
export { default as command } from './command.js';
Loading

0 comments on commit 59d6bde

Please sign in to comment.