From e455bf4478e5d36cd22f36abdbec61e944e39ab0 Mon Sep 17 00:00:00 2001 From: fabienpuissant Date: Thu, 5 Dec 2024 10:07:29 +0100 Subject: [PATCH] plug jhipster lite --- .editorconfig | 20 + .gitattributes | 152 ++ .github/actions/setup/action.yml | 23 + .github/workflows/github-actions.yml | 31 + .gitignore | 169 ++- .husky/pre-commit | 1 + .jhipster/modules/history.json | 59 + .lintstagedrc.cjs | 3 + .npmrc | 1 + .prettierignore | 5 + .prettierrc | 23 + README.md | 17 +- build.gradle | 62 - build.gradle.kts | 98 ++ checkstyle.xml | 48 + gradle/libs.versions.toml | 44 + gradlew | 0 package-lock.json | 1304 +++++++++++++++++ package.json | 25 + settings.gradle => settings.gradle.kts | 0 .../FluentBuilderApplicationService.java | 18 +- .../fluent/builder/domain/BuilderField.java | 73 +- .../domain/BuilderGeneratorDomainService.java | 516 ++++--- .../fluent/builder/domain/BuilderPort.java | 3 +- .../fluent/builder/domain/ExistingClass.java | 133 +- .../fluent/builder/domain/Field.java | 101 +- .../fluent/builder/domain/Fields.java | 12 +- .../domain/FluentBuilderParameters.java | 75 +- .../fluent/builder/domain/Interface.java | 73 +- .../fluent/builder/domain/Method.java | 75 +- .../domain/outputcommand/BuilderCommand.java | 6 +- .../outputcommand/BuilderCommandOutput.java | 5 +- .../domain/outputcommand/CommandContent.java | 47 +- .../domain/outputcommand/CommandScope.java | 4 +- .../outputcommand/CommandSignature.java | 6 +- .../domain/outputcommand/CreateCommand.java | 173 ++- .../domain/outputcommand/DeleteCommand.java | 141 +- .../domain/outputcommand/TargetName.java | 7 +- .../domain/outputcommand/TargetType.java | 10 +- .../builder/icons/FluentBuilderIcon.java | 7 +- .../primary/DialogFieldArrangement.java | 235 +-- .../primary/DialogFieldSelection.java | 127 +- .../primary/FluentBuilderAction.java | 42 +- .../FluentBuilderParametersMapper.java | 246 ++-- .../infrastructure/primary/Message.java | 29 +- .../secondary/FluentBuilderGenerator.java | 113 +- .../secondary/PsiClassService.java | 6 +- .../secondary/PsiClassServiceImpl.java | 24 +- .../commands/ClassCommandHandler.java | 34 +- .../secondary/commands/CommandHandler.java | 18 +- .../commands/CommandHandlerRegistry.java | 24 +- .../commands/ConstructorCommandHandler.java | 42 +- .../commands/FieldCommandHandler.java | 30 +- .../commands/InterfaceCommandHandler.java | 48 +- .../commands/MethodCommandHandler.java | 31 +- src/main/resources/META-INF/plugin.xml | 61 +- src/main/resources/META-INF/pluginIcon.svg | 17 +- src/main/resources/icons/moveDown.svg | 17 +- src/main/resources/icons/moveUp.svg | 19 +- .../fluent/builder/BuilderIT.java | 9 + .../BuilderGeneratorDomainServiceTest.java | 754 +++++----- .../builder/domain/FluentBuilderFixtures.java | 374 ++--- 62 files changed, 3871 insertions(+), 1999 deletions(-) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/actions/setup/action.yml create mode 100644 .github/workflows/github-actions.yml create mode 100644 .husky/pre-commit create mode 100644 .jhipster/modules/history.json create mode 100644 .lintstagedrc.cjs create mode 100644 .npmrc create mode 100644 .prettierignore create mode 100644 .prettierrc delete mode 100644 build.gradle create mode 100644 build.gradle.kts create mode 100644 checkstyle.xml create mode 100644 gradle/libs.versions.toml mode change 100644 => 100755 gradlew create mode 100644 package-lock.json create mode 100644 package.json rename settings.gradle => settings.gradle.kts (100%) create mode 100644 src/test/io/fabienpuissant/fluent/builder/BuilderIT.java diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..4d13f06 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,20 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + +[*] + +# We recommend you to keep these unchanged +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +# Change these settings to your own preference +indent_style = space +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..a425fdc --- /dev/null +++ b/.gitattributes @@ -0,0 +1,152 @@ +# This file is inspired by https://github.com/alexkaratarakis/gitattributes +# +# Auto detect text files and perform LF normalization +* text=auto + +# The above will handle all files NOT found below +# These files are text and should be normalized (Convert crlf => lf) + +*.bat text eol=crlf +*.cmd text eol=crlf +*.ps1 text eol=crlf +*.coffee text +*.css text +*.cql text +*.df text +*.ejs text +*.feature text +*.html text +*.java text +*.js text +*.json text +*.kts text +*.less text +*.properties text +*.sass text +*.scss text +*.sh text eol=lf +*.sql text +*.txt text +*.toml text +*.ts text +*.xml text +*.yaml text +*.yml text + +# Documents +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain +*.markdown text +*.md text +*.adoc text +*.textile text +*.mustache text +*.csv text +*.tab text +*.tsv text +*.txt text +AUTHORS text +CHANGELOG text +CHANGES text +CONTRIBUTING text +COPYING text +copyright text +*COPYRIGHT* text +INSTALL text +license text +LICENSE text +NEWS text +readme text +*README* text +TODO text + +# Graphics +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.tif binary +*.tiff binary +*.ico binary +# SVG treated as an asset (binary) by default. If you want to treat it as text, +# comment-out the following line and uncomment the line after. +*.svg binary +#*.svg text +*.eps binary + +# These files are binary and should be left untouched +# (binary is a macro for -text -diff) +*.class binary +*.jar binary +*.war binary + +## LINTERS +.csslintrc text +.eslintrc text +.jscsrc text +.jshintrc text +.jshintignore text +.stylelintrc text + +## CONFIGS +*.conf text +*.config text +.editorconfig text +.gitattributes text +.gitconfig text +.gitignore text +.htaccess text +*.npmignore text + +## HEROKU +Procfile text +.slugignore text + +## AUDIO +*.kar binary +*.m4a binary +*.mid binary +*.midi binary +*.mp3 binary +*.ogg binary +*.ra binary + +## VIDEO +*.3gpp binary +*.3gp binary +*.as binary +*.asf binary +*.asx binary +*.fla binary +*.flv binary +*.m4v binary +*.mng binary +*.mov binary +*.mp4 binary +*.mpeg binary +*.mpg binary +*.swc binary +*.swf binary +*.webm binary + +## ARCHIVES +*.7z binary +*.gz binary +*.rar binary +*.tar binary +*.zip binary + +## FONTS +*.ttf binary +*.eot binary +*.otf binary +*.woff binary +*.woff2 binary diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml new file mode 100644 index 0000000..8618458 --- /dev/null +++ b/.github/actions/setup/action.yml @@ -0,0 +1,23 @@ +name: 'Setup' +description: 'Setup environment with Java 21, Node 20' +runs: + using: 'composite' + steps: + - name: 'Setup: Node.js' + uses: actions/setup-node@v4 + with: + node-version: 22.11.0 + - name: 'Setup: update NPM' + shell: bash + run: npm install -g npm + - name: 'Setup: Java' + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: 21 + - name: 'Setup: check tools' + shell: bash + run: | + node -v + npm -v + java -version diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml new file mode 100644 index 0000000..7915ca2 --- /dev/null +++ b/.github/workflows/github-actions.yml @@ -0,0 +1,31 @@ +name: build +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || (github.ref == 'refs/heads/main' && github.sha) || github.ref }} + cancel-in-progress: true +on: + push: + branches: + - main + pull_request: + branches: + - main +jobs: + #-------------------------------------------------- + # Build and Tests the project on Linux + #-------------------------------------------------- + tests: + name: tests + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - name: 'Setup: checkout project' + uses: actions/checkout@v4 + - name: 'Setup: environment' + id: setup + uses: ./.github/actions/setup + - name: Setup Gradle + uses: gradle/gradle-build-action@v2 + - name: 'Test: run unit tests' + run: ./gradlew clean test --no-daemon + - name: 'Test: run integration tests' + run: ./gradlew integrationTest --no-daemon diff --git a/.gitignore b/.gitignore index faaa7f2..7fc254a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,45 +1,136 @@ -.gradle -build/ -!gradle/wrapper/gradle-wrapper.jar -!**/src/main/**/build/ -!**/src/test/**/build/ - -### IntelliJ IDEA ### -.idea/modules.xml -.idea/jarRepositories.xml -.idea/compiler.xml -.idea/libraries/ -*.iws +###################### +# Node +###################### +/node/ +node_tmp/ +node_modules/ +npm-debug.log.* +/.awcache/* +/.cache-loader/* + +###################### +# SASS +###################### +.sass-cache/ + +###################### +# Eclipse +###################### +*.pydevproject +.project +.metadata +tmp/ +tmp/**/* +*.tmp +*.bak +*.swp +*~.nib +local.properties +.classpath +.settings/ +.loadpath +.factorypath +/src/main/resources/rebel.xml + +# External tool builders +.externalToolBuilders/** + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# PDT-specific +.buildpath + +# STS-specific +/.sts4-cache/* + +###################### +# IntelliJ +###################### +.idea/ +.intellijPlatform/ *.iml +*.iws *.ipr +*.ids +*.orig +classes/ out/ -!**/src/main/**/out/ -!**/src/test/**/out/ -### Eclipse ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache -bin/ -!**/src/main/**/bin/ -!**/src/test/**/bin/ - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ - -### VS Code ### -.vscode/ - -### Mac OS ### +###################### +# Visual Studio Code +###################### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +###################### +# Maven +###################### +/target/ + +###################### +# Package Files +###################### +*.jar +*.war +*.ear +*.db + +###################### +# Windows +###################### +# Windows image file caches +Thumbs.db + +# Folder config file +Desktop.ini + +###################### +# Mac OSX +###################### .DS_Store +.svn + +# Thumbnails +._* + +# Files that might appear on external disk +.Spotlight-V100 +.Trashes + +###################### +# Directories +###################### +/bin/ +/deploy/ + +###################### +# Logs +###################### +*.log* + +###################### +# Others +###################### +*.class +*.*~ +*~ +.merge_file* +.attach_pid* -.idea -.run \ No newline at end of file +###################### +# ESLint +###################### +.eslintcache +# Gradle +/.gradle/ +/build/ +./buildSrc/.gradle/ +./buildSrc/build/ diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..c27d889 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +lint-staged diff --git a/.jhipster/modules/history.json b/.jhipster/modules/history.json new file mode 100644 index 0000000..7e8a5b6 --- /dev/null +++ b/.jhipster/modules/history.json @@ -0,0 +1,59 @@ +{ + "actions": [ + { + "module": "init", + "date": "2024-12-05T08:50:30.682968300Z", + "properties": { + "packageName": "io.fabienpuissant.fluent.builder", + "projectName": "Intellij java fluent builder", + "baseName": "intellijFluentBuilder", + "endOfLine": "lf", + "indentSize": 2 + } + }, + { + "module": "gradle-java", + "date": "2024-12-05T08:50:30.780966100Z", + "properties": { + "packageName": "io.fabienpuissant.fluent.builder", + "projectName": "Intellij java fluent builder", + "baseName": "intellijFluentBuilder", + "endOfLine": "lf", + "indentSize": 2 + } + }, + { + "module": "prettier", + "date": "2024-12-05T08:50:30.823966800Z", + "properties": { + "packageName": "io.fabienpuissant.fluent.builder", + "projectName": "Intellij java fluent builder", + "baseName": "intellijFluentBuilder", + "endOfLine": "lf", + "indentSize": 2 + } + }, + { + "module": "checkstyle", + "date": "2024-12-05T08:50:30.866533900Z", + "properties": { + "packageName": "io.fabienpuissant.fluent.builder", + "projectName": "Intellij java fluent builder", + "baseName": "intellijFluentBuilder", + "endOfLine": "lf", + "indentSize": 2 + } + }, + { + "module": "github-actions-gradle", + "date": "2024-12-05T08:50:30.888184600Z", + "properties": { + "packageName": "io.fabienpuissant.fluent.builder", + "projectName": "Intellij java fluent builder", + "baseName": "intellijFluentBuilder", + "endOfLine": "lf", + "indentSize": 2 + } + } + ] +} diff --git a/.lintstagedrc.cjs b/.lintstagedrc.cjs new file mode 100644 index 0000000..ce7f9a4 --- /dev/null +++ b/.lintstagedrc.cjs @@ -0,0 +1,3 @@ +module.exports = { + '*.{md,json,yml,html,css,scss,java,xml,feature}': ['prettier --write'], +}; diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..cffe8cd --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +save-exact=true diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..a245c77 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +target +build +package-lock.json +gradle +.gradle diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..95417fe --- /dev/null +++ b/.prettierrc @@ -0,0 +1,23 @@ +# Prettier configuration + +printWidth: 140 +singleQuote: true +tabWidth: 2 +useTabs: false +endOfLine: 'lf' + +plugins: + - '@prettier/plugin-xml' + - prettier-plugin-gherkin + - prettier-plugin-java + - prettier-plugin-organize-imports + - prettier-plugin-packagejson + +# js and ts rules: +arrowParens: avoid + +# jsx and tsx rules: +bracketSameLine: false + +# xml rules: +xmlWhitespaceSensitivity: ignore diff --git a/README.md b/README.md index 3820f5b..976f004 100644 --- a/README.md +++ b/README.md @@ -9,17 +9,18 @@ The **IntelliJ Fluent Builder Plugin** is your go-to solution for generating and 2. **Highly Adaptable Builders** Customize your builder to fit your exact needs: - - Modify parameter types or names. - - Remove parameters to simplify your builder. - - Make parameters optional to suit different use cases. - - Reorder parameters for better readability and usability. - The plugin automatically adjusts the builder interfaces and methods to reflect your changes, ensuring a consistent and reliable builder. + + - Modify parameter types or names. + - Remove parameters to simplify your builder. + - Make parameters optional to suit different use cases. + - Reorder parameters for better readability and usability. + The plugin automatically adjusts the builder interfaces and methods to reflect your changes, ensuring a consistent and reliable builder. 3. **Seamless Compatibility with Existing Code** The plugin adheres to established naming conventions to ensure compatibility with your existing project: - - **Builder Class Names**: `ClassNameBuilder` - - **Builder Interface Names**: `ClassNameParamBuilder` - This ensures that your generated builders integrate seamlessly into your current workflow. + - **Builder Class Names**: `ClassNameBuilder` + - **Builder Interface Names**: `ClassNameParamBuilder` + This ensures that your generated builders integrate seamlessly into your current workflow. ## Hexagonal Architecture Support diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 2c749a2..0000000 --- a/build.gradle +++ /dev/null @@ -1,62 +0,0 @@ -plugins { - id("java") - id("org.jetbrains.intellij.platform") version "2.1.0" -} - - -repositories { - intellijPlatform { - defaultRepositories() - mavenCentral() - } -} - -dependencies { - - intellijPlatform { - intellijIdeaCommunity("2024.3") - - bundledPlugin("com.intellij.java") - - - pluginVerifier() - zipSigner() - instrumentationTools() - - } - - testImplementation("org.junit.jupiter:junit-jupiter:5.11.3") - testImplementation("org.assertj:assertj-core:3.26.3") - testImplementation("org.mockito:mockito-core:5.14.2") - testImplementation("org.mockito:mockito-junit-jupiter:5.14.2") - testImplementation('org.junit.platform:junit-platform-console-standalone:1.11.3') -} - -sourceSets { -} - -sourceSets { - main { - java.srcDirs("src/main") - } - test { - java.srcDirs("src/test") - - resources { - srcDir 'src/test/resources' - } - } -} - -tasks { - - // Configure tests - test { - jvmArgs = ["-Djava.security.manager=allow"] - useJUnitPlatform() // Ensures JUnit 5 is used - } - - runIde { - jvmArgs = ["-Djava.security.manager=allow"] - } -} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..d6b80e7 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,98 @@ +// jhipster-needle-gradle-imports + +plugins { + checkstyle + id("java") + id("org.jetbrains.intellij.platform") version "2.1.0" + // jhipster-needle-gradle-plugins +} + +// jhipster-needle-gradle-properties + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } +} + +checkstyle { + configFile = rootProject.file("checkstyle.xml") + toolVersion = libs.versions.checkstyle.get() +} + +// jhipster-needle-gradle-plugins-configurations + +repositories { + intellijPlatform { + defaultRepositories() + mavenCentral() + } + mavenCentral() + // jhipster-needle-gradle-repositories +} + +val profiles = (project.findProperty("profiles") as String? ?: "") + .split(",") + .map { it.trim() } + .filter { it.isNotEmpty() } +// jhipster-needle-profile-activation + +dependencies { + + intellijPlatform { + intellijIdeaCommunity("2024.3") + + bundledPlugin("com.intellij.java") + + + pluginVerifier() + zipSigner() + instrumentationTools() + + } + + // jhipster-needle-gradle-implementation-dependencies + // jhipster-needle-gradle-compile-dependencies + // jhipster-needle-gradle-runtime-dependencies + testImplementation(libs.junit.engine) + testImplementation(libs.junit.params) + testImplementation(libs.assertj) + testImplementation(libs.mockito) + testImplementation(libs.junit.platform.console.standalone) + // jhipster-needle-gradle-test-dependencies +} + +sourceSets { +} + +sourceSets { + main { + java.srcDirs("src/main") + } + test { + java.srcDirs("src/test") + } +} + +// jhipster-needle-gradle-free-configuration-blocks + +tasks.test { + filter { + includeTestsMatching("**Test*") + excludeTestsMatching("**IT*") + excludeTestsMatching("**CucumberTest*") + } + useJUnitPlatform() + // jhipster-needle-gradle-tasks-test +} + +val integrationTest = task("integrationTest") { + description = "Runs integration tests." + group = "verification" + shouldRunAfter("test") + filter { + includeTestsMatching("**IT*") + includeTestsMatching("**CucumberTest*") + } + useJUnitPlatform() +} diff --git a/checkstyle.xml b/checkstyle.xml new file mode 100644 index 0000000..59e2f01 --- /dev/null +++ b/checkstyle.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..c9d3c2c --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,44 @@ +plugins = {} +bundles = {} + +[versions] + assertj = "3.26.3" + mockito = "5.14.2" + checkstyle = "10.20.2" + junit-jupiter = "5.11.3" + junit-platform-console-standalone = "1.11.3" + + [libraries.junit-params] + name = "junit-jupiter-params" + group = "org.junit.jupiter" + + [libraries.junit-params.version] + ref = "junit-jupiter" + + [libraries.assertj] + name = "assertj-core" + group = "org.assertj" + + [libraries.assertj.version] + ref = "assertj" + + [libraries.junit-engine] + name = "junit-jupiter-engine" + group = "org.junit.jupiter" + + [libraries.junit-engine.version] + ref = "junit-jupiter" + + [libraries.junit-platform-console-standalone] + name = "junit-platform-console-standalone" + group = "org.junit.platform" + + [libraries.junit-platform-console-standalone.version] + ref = "junit-platform-console-standalone" + + [libraries.mockito] + name = "mockito-junit-jupiter" + group = "org.mockito" + + [libraries.mockito.version] + ref = "mockito" diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..5229614 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1304 @@ +{ + "name": "intellij-fluent-builder", + "version": "1.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "intellij-fluent-builder", + "version": "1.0.1", + "license": "Apache-2.0", + "devDependencies": { + "@prettier/plugin-xml": "3.4.1", + "husky": "9.1.7", + "lint-staged": "15.2.10", + "prettier": "3.4.1", + "prettier-plugin-gherkin": "3.1.0", + "prettier-plugin-java": "2.6.5", + "prettier-plugin-organize-imports": "4.1.0", + "prettier-plugin-packagejson": "2.5.6" + }, + "engines": { + "node": ">=22" + } + }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", + "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/gast": "11.0.3", + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/gast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", + "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", + "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/types": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", + "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/utils": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", + "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@cucumber/gherkin": { + "version": "27.0.0", + "resolved": "https://registry.npmjs.org/@cucumber/gherkin/-/gherkin-27.0.0.tgz", + "integrity": "sha512-j5rCsjqzRiC3iVTier3sa0kzyNbkcAmF7xr7jKnyO7qDeK3Z8Ye1P3KSVpeQRMY+KCDJ3WbTDdyxH0FwfA/fIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cucumber/messages": ">=19.1.4 <=22" + } + }, + "node_modules/@cucumber/gherkin/node_modules/@cucumber/messages": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-22.0.0.tgz", + "integrity": "sha512-EuaUtYte9ilkxcKmfqGF9pJsHRUU0jwie5ukuZ/1NPTuHS1LxHPsGEODK17RPRbZHOFhqybNzG2rHAwThxEymg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/uuid": "9.0.1", + "class-transformer": "0.5.1", + "reflect-metadata": "0.1.13", + "uuid": "9.0.0" + } + }, + "node_modules/@cucumber/gherkin/node_modules/@types/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cucumber/gherkin/node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@cucumber/messages": { + "version": "23.0.0", + "resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-23.0.0.tgz", + "integrity": "sha512-2ZWKNnikNMBnle3P3cgy+fgzhABrY4oBbiWp9wcI8ANdT4LlYRN6jQ6j/9CQGTDGRfkyRtr/5VkYq7q24XCsuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/uuid": "9.0.6", + "class-transformer": "0.5.1", + "reflect-metadata": "0.1.13", + "uuid": "9.0.1" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@prettier/plugin-xml": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@prettier/plugin-xml/-/plugin-xml-3.4.1.tgz", + "integrity": "sha512-Uf/6/+9ez6z/IvZErgobZ2G9n1ybxF5BhCd7eMcKqfoWuOzzNUxBipNo3QAP8kRC1VD18TIo84no7LhqtyDcTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@xml-tools/parser": "^1.0.11" + }, + "peerDependencies": { + "prettier": "^3.0.0" + } + }, + "node_modules/@types/uuid": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.6.tgz", + "integrity": "sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew==", + "dev": true, + "license": "MIT" + }, + "node_modules/@xml-tools/parser": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@xml-tools/parser/-/parser-1.0.11.tgz", + "integrity": "sha512-aKqQ077XnR+oQtHJlrAflaZaL7qZsulWc/i/ZEooar5JiWj1eLt0+Wg28cpa+XLney107wXqneC+oG1IZvxkTA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "chevrotain": "7.1.1" + } + }, + "node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chevrotain": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-7.1.1.tgz", + "integrity": "sha512-wy3mC1x4ye+O+QkEinVJkPf5u2vsrDIYW9G7ZuwFl6v/Yu0LwUuT2POsb+NUWApebyxfkQq6+yDfRExbnI5rcw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "regexp-to-ast": "0.5.0" + } + }, + "node_modules/class-transformer": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==", + "dev": true, + "license": "MIT" + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/detect-indent": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz", + "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/detect-newline": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-4.0.1.tgz", + "integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true, + "license": "MIT" + }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-hooks-list": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-3.1.0.tgz", + "integrity": "sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/fisker/git-hooks-list?sponsor=1" + } + }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/java-parser": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/java-parser/-/java-parser-2.3.2.tgz", + "integrity": "sha512-/O42UbEHy3VVJw8W0ruHkQjW75oWvQx4QisoUDRIGir6q3/IZ4JslDMPMYEqp7LU56PYJkH5uXdQiBaCXt/Opw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "chevrotain": "11.0.3", + "chevrotain-allstar": "0.3.1", + "lodash": "4.17.21" + } + }, + "node_modules/java-parser/node_modules/chevrotain": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", + "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/cst-dts-gen": "11.0.3", + "@chevrotain/gast": "11.0.3", + "@chevrotain/regexp-to-ast": "11.0.3", + "@chevrotain/types": "11.0.3", + "@chevrotain/utils": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/java-parser/node_modules/chevrotain-allstar": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/chevrotain-allstar/-/chevrotain-allstar-0.3.1.tgz", + "integrity": "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash-es": "^4.17.21" + }, + "peerDependencies": { + "chevrotain": "^11.0.0" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lint-staged": { + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.10.tgz", + "integrity": "sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "~5.3.0", + "commander": "~12.1.0", + "debug": "~4.3.6", + "execa": "~8.0.1", + "lilconfig": "~3.1.2", + "listr2": "~8.2.4", + "micromatch": "~4.0.8", + "pidtree": "~0.6.0", + "string-argv": "~0.3.2", + "yaml": "~2.5.0" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/listr2": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", + "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/prettier": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.1.tgz", + "integrity": "sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-gherkin": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/prettier-plugin-gherkin/-/prettier-plugin-gherkin-3.1.0.tgz", + "integrity": "sha512-3YXeJI2cEbVPOrLvjVgFACqmZ1d2gpTkyTn74OTAUXAH8F6E8v6SFSXFGiurWlW4hwbGBINKGNUbU3iDiIuT4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cucumber/gherkin": "^27.0.0", + "@cucumber/messages": "^23.0.0", + "prettier": "^3.0.0" + } + }, + "node_modules/prettier-plugin-java": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/prettier-plugin-java/-/prettier-plugin-java-2.6.5.tgz", + "integrity": "sha512-2RkPNXyYpP5dRhr04pz45n+e5LXwYWTh1JXrztiCkZTGGokIGYrfwUuGa8csnDoGbP6CDPgVm8zZSIm/9I0SRQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "java-parser": "2.3.2", + "lodash": "4.17.21", + "prettier": "3.2.5" + } + }, + "node_modules/prettier-plugin-java/node_modules/prettier": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-organize-imports": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-4.1.0.tgz", + "integrity": "sha512-5aWRdCgv645xaa58X8lOxzZoiHAldAPChljr/MT0crXVOWTZ+Svl4hIWlz+niYSlO6ikE5UXkN1JrRvIP2ut0A==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "prettier": ">=2.0", + "typescript": ">=2.9", + "vue-tsc": "^2.1.0" + }, + "peerDependenciesMeta": { + "vue-tsc": { + "optional": true + } + } + }, + "node_modules/prettier-plugin-packagejson": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.6.tgz", + "integrity": "sha512-TY7KiLtyt6Tlf53BEbXUWkN0+TRdHKgIMmtXtDCyHH6yWnZ50Lwq6Vb6lyjapZrhDTXooC4EtlY5iLe1sCgi5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "sort-package-json": "2.12.0", + "synckit": "0.9.2" + }, + "peerDependencies": { + "prettier": ">= 1.16.0" + }, + "peerDependenciesMeta": { + "prettier": { + "optional": true + } + } + }, + "node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/regexp-to-ast": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", + "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==", + "dev": true, + "license": "MIT" + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/sort-object-keys": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz", + "integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sort-package-json": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.12.0.tgz", + "integrity": "sha512-/HrPQAeeLaa+vbAH/znjuhwUluuiM/zL5XX9kop8UpDgjtyWKt43hGDk2vd/TBdDpzIyzIHVUgmYofzYrAQjew==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-indent": "^7.0.1", + "detect-newline": "^4.0.0", + "get-stdin": "^9.0.0", + "git-hooks-list": "^3.0.0", + "is-plain-obj": "^4.1.0", + "semver": "^7.6.0", + "sort-object-keys": "^1.1.3", + "tinyglobby": "^0.2.9" + }, + "bin": { + "sort-package-json": "cli.js" + } + }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/synckit": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", + "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", + "integrity": "sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", + "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/yaml": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..45e62de --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "intellij-fluent-builder", + "version": "1.0.1", + "private": true, + "description": "Intellij java fluent builder", + "license": "Apache-2.0", + "scripts": { + "prepare": "husky", + "prettier:check": "prettier --check .", + "prettier:format": "prettier --write ." + }, + "devDependencies": { + "@prettier/plugin-xml": "3.4.1", + "husky": "9.1.7", + "lint-staged": "15.2.10", + "prettier": "3.4.1", + "prettier-plugin-gherkin": "3.1.0", + "prettier-plugin-java": "2.6.5", + "prettier-plugin-organize-imports": "4.1.0", + "prettier-plugin-packagejson": "2.5.6" + }, + "engines": { + "node": ">=22" + } +} diff --git a/settings.gradle b/settings.gradle.kts similarity index 100% rename from settings.gradle rename to settings.gradle.kts diff --git a/src/main/java/io/fabienpuissant/fluent/builder/application/FluentBuilderApplicationService.java b/src/main/java/io/fabienpuissant/fluent/builder/application/FluentBuilderApplicationService.java index d6862f6..47b0e25 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/application/FluentBuilderApplicationService.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/application/FluentBuilderApplicationService.java @@ -1,23 +1,21 @@ package io.fabienpuissant.fluent.builder.application; +import com.intellij.psi.PsiField; import io.fabienpuissant.fluent.builder.domain.BuilderGeneratorDomainService; import io.fabienpuissant.fluent.builder.infrastructure.primary.FluentBuilderParametersMapper; import io.fabienpuissant.fluent.builder.infrastructure.primary.PluginContext; import io.fabienpuissant.fluent.builder.infrastructure.secondary.FluentBuilderGenerator; -import com.intellij.psi.PsiField; - import java.util.List; public class FluentBuilderApplicationService { - private final BuilderGeneratorDomainService builder; - - public FluentBuilderApplicationService() { - this.builder = new BuilderGeneratorDomainService(new FluentBuilderGenerator()); - } + private final BuilderGeneratorDomainService builder; - public void generateBuilder(PluginContext context, List mandatoryFields, List optionalFields) { - builder.generateBuilder(FluentBuilderParametersMapper.toDomain(context, mandatoryFields, optionalFields)); - } + public FluentBuilderApplicationService() { + this.builder = new BuilderGeneratorDomainService(new FluentBuilderGenerator()); + } + public void generateBuilder(PluginContext context, List mandatoryFields, List optionalFields) { + builder.generateBuilder(FluentBuilderParametersMapper.toDomain(context, mandatoryFields, optionalFields)); + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/domain/BuilderField.java b/src/main/java/io/fabienpuissant/fluent/builder/domain/BuilderField.java index 2896dda..b16af13 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/domain/BuilderField.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/domain/BuilderField.java @@ -1,53 +1,54 @@ package io.fabienpuissant.fluent.builder.domain; public class BuilderField { - private final String name; - private final String type; - public String name() { - return name; - } + private final String name; + private final String type; - public String type() { - return type; - } + public String name() { + return name; + } - private BuilderField(BuilderFieldBuilder builder) { - assert builder.name != null && builder.type != null; + public String type() { + return type; + } - this.name = builder.name; - this.type = builder.type; - } + private BuilderField(BuilderFieldBuilder builder) { + assert builder.name != null && builder.type != null; - public static BuilderFieldNameBuilder builder() { - return new BuilderFieldBuilder(); - } + this.name = builder.name; + this.type = builder.type; + } - public sealed interface BuilderFieldNameBuilder permits BuilderFieldBuilder { - BuilderFieldTypeBuilder name(String name); - } + public static BuilderFieldNameBuilder builder() { + return new BuilderFieldBuilder(); + } - public sealed interface BuilderFieldTypeBuilder permits BuilderFieldBuilder { - BuilderField type(String type); - } + public sealed interface BuilderFieldNameBuilder permits BuilderFieldBuilder { + BuilderFieldTypeBuilder name(String name); + } - private static final class BuilderFieldBuilder implements BuilderFieldNameBuilder, BuilderFieldTypeBuilder { - private String name; - private String type; + public sealed interface BuilderFieldTypeBuilder permits BuilderFieldBuilder { + BuilderField type(String type); + } - @Override - public BuilderFieldTypeBuilder name(String name) { - this.name = name; + private static final class BuilderFieldBuilder implements BuilderFieldNameBuilder, BuilderFieldTypeBuilder { - return this; - } + private String name; + private String type; - @Override - public BuilderField type(String type) { - this.type = type; + @Override + public BuilderFieldTypeBuilder name(String name) { + this.name = name; - return new BuilderField(this); - } + return this; } -} + @Override + public BuilderField type(String type) { + this.type = type; + + return new BuilderField(this); + } + } +} diff --git a/src/main/java/io/fabienpuissant/fluent/builder/domain/BuilderGeneratorDomainService.java b/src/main/java/io/fabienpuissant/fluent/builder/domain/BuilderGeneratorDomainService.java index c610e05..41685df 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/domain/BuilderGeneratorDomainService.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/domain/BuilderGeneratorDomainService.java @@ -1,7 +1,9 @@ package io.fabienpuissant.fluent.builder.domain; -import io.fabienpuissant.fluent.builder.domain.outputcommand.*; +import static java.util.function.Predicate.*; +import static org.apache.commons.lang3.StringUtils.capitalize; +import io.fabienpuissant.fluent.builder.domain.outputcommand.*; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -10,261 +12,295 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; -import static java.util.function.Predicate.*; -import static org.apache.commons.lang3.StringUtils.capitalize; - public class BuilderGeneratorDomainService { - private final BuilderPort builderPort; - - public BuilderGeneratorDomainService(BuilderPort builderPort) { - this.builderPort = builderPort; - } - - public void generateBuilder(FluentBuilderParameters fluentBuilderParameters) { - List commands = new ArrayList<>(); - commands.addAll(interfacesCommands(fluentBuilderParameters)); - commands.addAll(builderCommands(fluentBuilderParameters)); - commands.addAll(builderFields(fluentBuilderParameters)); - commands.addAll(builderInterfacesCommands(fluentBuilderParameters)); - commands.addAll(buildMethod(fluentBuilderParameters)); - commands.addAll(buildConstructor(fluentBuilderParameters)); - commands.addAll(builderMethod(fluentBuilderParameters)); - builderPort.generateBuilder(new BuilderCommandOutput(commands)); - } - - private List interfacesCommands(FluentBuilderParameters fluentBuilderParameters) { - List commands = new ArrayList<>(); - commands.addAll(interfacesToRemove(fluentBuilderParameters.existingClass())); - - interfacesToCreate(fluentBuilderParameters, commands); - - return commands; - } - - private void interfacesToCreate(FluentBuilderParameters fluentBuilderParameters, List commands) { - List mandatoryParams = fluentBuilderParameters.parameters().fields().stream().filter(not(Field::isOptional)).toList(); - List optionalParams = fluentBuilderParameters.parameters().fields().stream().filter(Field::isOptional).toList(); - String className = fluentBuilderParameters.existingClass().className(); - - for (int i = 0; i < mandatoryParams.size(); i++) { - Field field = mandatoryParams.get(i); - String currentInterfaceName = interfaceNameForParameter(field, className); - boolean isLastMandatoryField = field.equals(mandatoryParams.getLast()); - StringBuilder nextInterfaceName = new StringBuilder(); - if(!isLastMandatoryField) { - nextInterfaceName.append(interfaceNameForParameter(mandatoryParams.get(i + 1), className)); - } else { - nextInterfaceName.append(optionalParams.isEmpty() ? className : "%sOptionalBuilder".formatted(className)); - } - - String interfaceContent = nextInterfaceName.toString().equals(className) - ? String.format("%s %s(%s %s);", className, field.name(), field.type(), field.name()) - : String.format("%s %s(%s %s);", nextInterfaceName, field.name(), field.type(), field.name()); - - commands.add(CreateCommand.builder() - .signature(new CommandSignature(String.format("public sealed interface %s permits %sBuilder", currentInterfaceName, className))) - .content(new CommandContent(interfaceContent)) - .scope(CommandScope.CLASS) - .type(TargetType.INTERFACE)); - } - - if (!optionalParams.isEmpty()) { - StringBuilder contentBuilder = new StringBuilder(); - for (Field field : optionalParams) { - contentBuilder.append("%sOptionalBuilder %s(%s %s);\n".formatted(className, field.name(), field.type(), field.name())); - } - contentBuilder.append("%s build();".formatted(className)); - - commands.add(CreateCommand.builder() - .signature(new CommandSignature("public sealed interface %sOptionalBuilder permits %sBuilder".formatted(className, className))) - .content(new CommandContent(contentBuilder.toString())) - .scope(CommandScope.CLASS) - .type(TargetType.INTERFACE)); - } - } - - private String interfaceNameForParameter(Field field, String className) { - return "%s%sBuilder".formatted(className, capitalize(field.name())); + private final BuilderPort builderPort; + + public BuilderGeneratorDomainService(BuilderPort builderPort) { + this.builderPort = builderPort; + } + + public void generateBuilder(FluentBuilderParameters fluentBuilderParameters) { + List commands = new ArrayList<>(); + commands.addAll(interfacesCommands(fluentBuilderParameters)); + commands.addAll(builderCommands(fluentBuilderParameters)); + commands.addAll(builderFields(fluentBuilderParameters)); + commands.addAll(builderInterfacesCommands(fluentBuilderParameters)); + commands.addAll(buildMethod(fluentBuilderParameters)); + commands.addAll(buildConstructor(fluentBuilderParameters)); + commands.addAll(builderMethod(fluentBuilderParameters)); + builderPort.generateBuilder(new BuilderCommandOutput(commands)); + } + + private List interfacesCommands(FluentBuilderParameters fluentBuilderParameters) { + List commands = new ArrayList<>(); + commands.addAll(interfacesToRemove(fluentBuilderParameters.existingClass())); + + interfacesToCreate(fluentBuilderParameters, commands); + + return commands; + } + + private void interfacesToCreate(FluentBuilderParameters fluentBuilderParameters, List commands) { + List mandatoryParams = fluentBuilderParameters.parameters().fields().stream().filter(not(Field::isOptional)).toList(); + List optionalParams = fluentBuilderParameters.parameters().fields().stream().filter(Field::isOptional).toList(); + String className = fluentBuilderParameters.existingClass().className(); + + for (int i = 0; i < mandatoryParams.size(); i++) { + Field field = mandatoryParams.get(i); + String currentInterfaceName = interfaceNameForParameter(field, className); + boolean isLastMandatoryField = field.equals(mandatoryParams.getLast()); + StringBuilder nextInterfaceName = new StringBuilder(); + if (!isLastMandatoryField) { + nextInterfaceName.append(interfaceNameForParameter(mandatoryParams.get(i + 1), className)); + } else { + nextInterfaceName.append(optionalParams.isEmpty() ? className : "%sOptionalBuilder".formatted(className)); + } + + String interfaceContent = nextInterfaceName.toString().equals(className) + ? String.format("%s %s(%s %s);", className, field.name(), field.type(), field.name()) + : String.format("%s %s(%s %s);", nextInterfaceName, field.name(), field.type(), field.name()); + + commands.add( + CreateCommand.builder() + .signature(new CommandSignature(String.format("public sealed interface %s permits %sBuilder", currentInterfaceName, className))) + .content(new CommandContent(interfaceContent)) + .scope(CommandScope.CLASS) + .type(TargetType.INTERFACE) + ); } - private List builderCommands(FluentBuilderParameters fluentBuilderParameters) { - List commands = new ArrayList<>(); - String builderName = fluentBuilderParameters.existingClass().className() + "Builder"; - - deleteExistingBuilder(fluentBuilderParameters, builderName).ifPresent(commands::add); - commands.add(createBuilder(fluentBuilderParameters, builderName)); - - return commands; - } - - private List builderFields(FluentBuilderParameters fluentBuilderParameters) { - List commands = new ArrayList<>(); - for (Field field : fluentBuilderParameters.parameters().fields()) { - commands.add(CreateCommand.builder() - .signature(new CommandSignature("private %s %s;".formatted(field.type(), field.name()))) - .content(new CommandContent(null)) - .scope(CommandScope.BUILDER) - .type(TargetType.FIELD)); - } - return commands; - } - - private static List builderInterfacesCommands(FluentBuilderParameters fluentBuilderParameters) { - List commands = new ArrayList<>(); - Iterator fieldIterator = fluentBuilderParameters.parameters().fields().iterator(); - - String existingClassName = fluentBuilderParameters.existingClass().className(); - Field currentField; - Field nextField = fieldIterator.hasNext() ? fieldIterator.next() : null; - - while (nextField != null) { - currentField = nextField; - nextField = fieldIterator.hasNext() ? fieldIterator.next() : null; - - boolean isOptionalFieldExist = fluentBuilderParameters.parameters().fields().stream().anyMatch(Field::isOptional); - String nextBuilder = isOptionalFieldExist ? existingClassName + "OptionalBuilder" : existingClassName; - String nextReturn = isOptionalFieldExist ? "this" : "new %s(this)".formatted(existingClassName); - - if (nextField != null) { - nextBuilder = nextField.isOptional() ? existingClassName + "Optional" : existingClassName + capitalize(nextField.name()); - nextBuilder += "Builder"; - nextReturn = "this"; - } - - commands.add(CreateCommand.builder() - .signature(new CommandSignature(""" - @Override - public %s %s(%s %s) - """.formatted(nextBuilder, currentField.name(), currentField.type(), currentField.name()))) - .content(new CommandContent(""" - this.%s = %s; - - return %s;""".formatted(currentField.name(), currentField.name(), nextReturn))) - .scope(CommandScope.BUILDER) - .type(TargetType.METHOD) - ); - } - - return commands; - } - - private List buildMethod(FluentBuilderParameters fluentBuilderParameters) { - if (fluentBuilderParameters.parameters().fields().stream().noneMatch(Field::isOptional)) { - return List.of(); - } - return List.of(CreateCommand.builder() - .signature(new CommandSignature("@Override\npublic %s build()".formatted(fluentBuilderParameters.existingClass().className()))) - .content(new CommandContent("return new %s(this);".formatted(fluentBuilderParameters.existingClass().className()))) - .scope(CommandScope.BUILDER) - .type(TargetType.METHOD)); - } - - private List buildConstructor(FluentBuilderParameters fluentBuilderParameters) { - List commands = new ArrayList<>(); - - if (isConstructorExists(fluentBuilderParameters)) { - commands.add(DeleteCommand.builder() - .name(new TargetName(fluentBuilderParameters.existingClass().className())) - .scope(CommandScope.CLASS) - .type(TargetType.CONSTRUCTOR)); - } - - String content = fluentBuilderParameters.parameters().fields().stream() - .map(field -> "this.%s = builder.%s;".formatted(field.name(), field.name())) - .collect(Collectors.joining("\n")); - commands.add(CreateCommand.builder() - .signature(new CommandSignature("private %s(%sBuilder builder)".formatted(fluentBuilderParameters.existingClass().className(), fluentBuilderParameters.existingClass().className()))) - .content(new CommandContent(content)) - .scope(CommandScope.CLASS) - .type(TargetType.CONSTRUCTOR)); - - return commands; + if (!optionalParams.isEmpty()) { + StringBuilder contentBuilder = new StringBuilder(); + for (Field field : optionalParams) { + contentBuilder.append("%sOptionalBuilder %s(%s %s);\n".formatted(className, field.name(), field.type(), field.name())); + } + contentBuilder.append("%s build();".formatted(className)); + + commands.add( + CreateCommand.builder() + .signature(new CommandSignature("public sealed interface %sOptionalBuilder permits %sBuilder".formatted(className, className))) + .content(new CommandContent(contentBuilder.toString())) + .scope(CommandScope.CLASS) + .type(TargetType.INTERFACE) + ); } - - private List builderMethod(FluentBuilderParameters fluentBuilderParameters) { - List commands = new ArrayList<>(); - - if (isIsBuilderMethodExist(fluentBuilderParameters, "builder()")) { - commands.add(DeleteCommand.builder() - .name(new TargetName("builder")) - .scope(CommandScope.CLASS) - .type(TargetType.METHOD)); - } - - String builderMethodSignature = "%s builder()".formatted(extractFirstInterfaceName(fluentBuilderParameters)); - commands.add(CreateCommand.builder() - .signature(new CommandSignature("public static %s".formatted(builderMethodSignature))) - .content(new CommandContent("return new %sBuilder();".formatted(fluentBuilderParameters.existingClass().className()))) - .scope(CommandScope.CLASS) - .type(TargetType.METHOD)); - return commands; + } + + private String interfaceNameForParameter(Field field, String className) { + return "%s%sBuilder".formatted(className, capitalize(field.name())); + } + + private List builderCommands(FluentBuilderParameters fluentBuilderParameters) { + List commands = new ArrayList<>(); + String builderName = fluentBuilderParameters.existingClass().className() + "Builder"; + + deleteExistingBuilder(fluentBuilderParameters, builderName).ifPresent(commands::add); + commands.add(createBuilder(fluentBuilderParameters, builderName)); + + return commands; + } + + private List builderFields(FluentBuilderParameters fluentBuilderParameters) { + List commands = new ArrayList<>(); + for (Field field : fluentBuilderParameters.parameters().fields()) { + commands.add( + CreateCommand.builder() + .signature(new CommandSignature("private %s %s;".formatted(field.type(), field.name()))) + .content(new CommandContent(null)) + .scope(CommandScope.BUILDER) + .type(TargetType.FIELD) + ); } - - - private static String extractFirstInterfaceName(FluentBuilderParameters fluentBuilderParameters) { - Field firstField = fluentBuilderParameters.parameters().fields().stream().findFirst().orElseThrow(); - if(fluentBuilderParameters.parameters().fields().stream().allMatch(Field::isOptional)) { - return "%sOptionalBuilder".formatted(fluentBuilderParameters.existingClass().className()); - } - return "%s%sBuilder".formatted(fluentBuilderParameters.existingClass().className(), capitalize(firstField.name())); + return commands; + } + + private static List builderInterfacesCommands(FluentBuilderParameters fluentBuilderParameters) { + List commands = new ArrayList<>(); + Iterator fieldIterator = fluentBuilderParameters.parameters().fields().iterator(); + + String existingClassName = fluentBuilderParameters.existingClass().className(); + Field currentField; + Field nextField = fieldIterator.hasNext() ? fieldIterator.next() : null; + + while (nextField != null) { + currentField = nextField; + nextField = fieldIterator.hasNext() ? fieldIterator.next() : null; + + boolean isOptionalFieldExist = fluentBuilderParameters.parameters().fields().stream().anyMatch(Field::isOptional); + String nextBuilder = isOptionalFieldExist ? existingClassName + "OptionalBuilder" : existingClassName; + String nextReturn = isOptionalFieldExist ? "this" : "new %s(this)".formatted(existingClassName); + + if (nextField != null) { + nextBuilder = nextField.isOptional() ? existingClassName + "Optional" : existingClassName + capitalize(nextField.name()); + nextBuilder += "Builder"; + nextReturn = "this"; + } + + commands.add( + CreateCommand.builder() + .signature( + new CommandSignature( + """ + @Override + public %s %s(%s %s) + """.formatted(nextBuilder, currentField.name(), currentField.type(), currentField.name()) + ) + ) + .content( + new CommandContent( + """ + this.%s = %s; + + return %s;""".formatted(currentField.name(), currentField.name(), nextReturn) + ) + ) + .scope(CommandScope.BUILDER) + .type(TargetType.METHOD) + ); } + return commands; + } - private static Optional deleteExistingBuilder(FluentBuilderParameters fluentBuilderParameters, String builderName) { - if (fluentBuilderParameters.existingClass().isBuilderExist()) { - return Optional.of(DeleteCommand.builder() - .name(new TargetName(builderName)) - .scope(CommandScope.CLASS) - .type(TargetType.CLASS)); - } - return Optional.empty(); + private List buildMethod(FluentBuilderParameters fluentBuilderParameters) { + if (fluentBuilderParameters.parameters().fields().stream().noneMatch(Field::isOptional)) { + return List.of(); } - - private static CreateCommand createBuilder(FluentBuilderParameters fluentBuilderParameters, String builderName) { - StringBuilder builderSignature = new StringBuilder("private static final class %s".formatted(builderName)); - addImplementedInterfaces(fluentBuilderParameters, builderSignature); - - return CreateCommand.builder() - .signature(new CommandSignature(builderSignature.toString())) - .content(new CommandContent(null)) - .scope(CommandScope.CLASS) - .type(TargetType.CLASS); + return List.of( + CreateCommand.builder() + .signature(new CommandSignature("@Override\npublic %s build()".formatted(fluentBuilderParameters.existingClass().className()))) + .content(new CommandContent("return new %s(this);".formatted(fluentBuilderParameters.existingClass().className()))) + .scope(CommandScope.BUILDER) + .type(TargetType.METHOD) + ); + } + + private List buildConstructor(FluentBuilderParameters fluentBuilderParameters) { + List commands = new ArrayList<>(); + + if (isConstructorExists(fluentBuilderParameters)) { + commands.add( + DeleteCommand.builder() + .name(new TargetName(fluentBuilderParameters.existingClass().className())) + .scope(CommandScope.CLASS) + .type(TargetType.CONSTRUCTOR) + ); } - private static void addImplementedInterfaces(FluentBuilderParameters fluentBuilderParameters, StringBuilder builderSignature) { - if (fluentBuilderParameters.parameters().fields().isEmpty()) return; - - builderSignature.append(" implements"); - fluentBuilderParameters.parameters().fields().stream().filter(not(Field::isOptional)).forEach(field -> builderSignature.append(" %s%sBuilder,".formatted(fluentBuilderParameters.existingClass().className(), capitalize(field.name())))); - if(fluentBuilderParameters.parameters().fields().stream().anyMatch(Field::isOptional)) { - builderSignature.append(" %sOptionalBuilder,".formatted(fluentBuilderParameters.existingClass().className())); - } - builderSignature.deleteCharAt(builderSignature.length() - 1); + String content = fluentBuilderParameters + .parameters() + .fields() + .stream() + .map(field -> "this.%s = builder.%s;".formatted(field.name(), field.name())) + .collect(Collectors.joining("\n")); + commands.add( + CreateCommand.builder() + .signature( + new CommandSignature( + "private %s(%sBuilder builder)".formatted( + fluentBuilderParameters.existingClass().className(), + fluentBuilderParameters.existingClass().className() + ) + ) + ) + .content(new CommandContent(content)) + .scope(CommandScope.CLASS) + .type(TargetType.CONSTRUCTOR) + ); + + return commands; + } + + private List builderMethod(FluentBuilderParameters fluentBuilderParameters) { + List commands = new ArrayList<>(); + + if (isIsBuilderMethodExist(fluentBuilderParameters, "builder()")) { + commands.add(DeleteCommand.builder().name(new TargetName("builder")).scope(CommandScope.CLASS).type(TargetType.METHOD)); } - private static List interfacesToRemove(ExistingClass existingClass) { - return existingClass.builderInterfaces().stream() - .map(inter -> DeleteCommand.builder() - .name(new TargetName(inter.name())) - .scope(CommandScope.CLASS) - .type(TargetType.INTERFACE) - ).toList(); + String builderMethodSignature = "%s builder()".formatted(extractFirstInterfaceName(fluentBuilderParameters)); + commands.add( + CreateCommand.builder() + .signature(new CommandSignature("public static %s".formatted(builderMethodSignature))) + .content(new CommandContent("return new %sBuilder();".formatted(fluentBuilderParameters.existingClass().className()))) + .scope(CommandScope.CLASS) + .type(TargetType.METHOD) + ); + return commands; + } + + private static String extractFirstInterfaceName(FluentBuilderParameters fluentBuilderParameters) { + Field firstField = fluentBuilderParameters.parameters().fields().stream().findFirst().orElseThrow(); + if (fluentBuilderParameters.parameters().fields().stream().allMatch(Field::isOptional)) { + return "%sOptionalBuilder".formatted(fluentBuilderParameters.existingClass().className()); } + return "%s%sBuilder".formatted(fluentBuilderParameters.existingClass().className(), capitalize(firstField.name())); + } - private static boolean isConstructorExists(FluentBuilderParameters fluentBuilderParameters) { - String className = fluentBuilderParameters.existingClass().className(); // e.g., "Test" - String regex = "\\b" +className + "\\([^)]*" + className + "Builder\\s+builder\\s*\\)"; - Pattern pattern = Pattern.compile(regex); - return fluentBuilderParameters.existingClass().classMethods().stream() - .anyMatch(method -> { - Matcher matcher = pattern.matcher(method.signature()); - return matcher.find(); - }); + private static Optional deleteExistingBuilder(FluentBuilderParameters fluentBuilderParameters, String builderName) { + if (fluentBuilderParameters.existingClass().isBuilderExist()) { + return Optional.of(DeleteCommand.builder().name(new TargetName(builderName)).scope(CommandScope.CLASS).type(TargetType.CLASS)); } - - - private static boolean isIsBuilderMethodExist(FluentBuilderParameters fluentBuilderParameters, String builderMethodSignature) { - return fluentBuilderParameters.existingClass().classMethods().stream().anyMatch(method -> method.signature().contains(builderMethodSignature)); + return Optional.empty(); + } + + private static CreateCommand createBuilder(FluentBuilderParameters fluentBuilderParameters, String builderName) { + StringBuilder builderSignature = new StringBuilder("private static final class %s".formatted(builderName)); + addImplementedInterfaces(fluentBuilderParameters, builderSignature); + + return CreateCommand.builder() + .signature(new CommandSignature(builderSignature.toString())) + .content(new CommandContent(null)) + .scope(CommandScope.CLASS) + .type(TargetType.CLASS); + } + + private static void addImplementedInterfaces(FluentBuilderParameters fluentBuilderParameters, StringBuilder builderSignature) { + if (fluentBuilderParameters.parameters().fields().isEmpty()) return; + + builderSignature.append(" implements"); + fluentBuilderParameters + .parameters() + .fields() + .stream() + .filter(not(Field::isOptional)) + .forEach(field -> + builderSignature.append(" %s%sBuilder,".formatted(fluentBuilderParameters.existingClass().className(), capitalize(field.name()))) + ); + if (fluentBuilderParameters.parameters().fields().stream().anyMatch(Field::isOptional)) { + builderSignature.append(" %sOptionalBuilder,".formatted(fluentBuilderParameters.existingClass().className())); } + builderSignature.deleteCharAt(builderSignature.length() - 1); + } + + private static List interfacesToRemove(ExistingClass existingClass) { + return existingClass + .builderInterfaces() + .stream() + .map(inter -> DeleteCommand.builder().name(new TargetName(inter.name())).scope(CommandScope.CLASS).type(TargetType.INTERFACE)) + .toList(); + } + + private static boolean isConstructorExists(FluentBuilderParameters fluentBuilderParameters) { + String className = fluentBuilderParameters.existingClass().className(); // e.g., "Test" + String regex = "\\b" + className + "\\([^)]*" + className + "Builder\\s+builder\\s*\\)"; + Pattern pattern = Pattern.compile(regex); + return fluentBuilderParameters + .existingClass() + .classMethods() + .stream() + .anyMatch(method -> { + Matcher matcher = pattern.matcher(method.signature()); + return matcher.find(); + }); + } + + private static boolean isIsBuilderMethodExist(FluentBuilderParameters fluentBuilderParameters, String builderMethodSignature) { + return fluentBuilderParameters + .existingClass() + .classMethods() + .stream() + .anyMatch(method -> method.signature().contains(builderMethodSignature)); + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/domain/BuilderPort.java b/src/main/java/io/fabienpuissant/fluent/builder/domain/BuilderPort.java index 5e41d00..1a6262d 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/domain/BuilderPort.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/domain/BuilderPort.java @@ -1,8 +1,7 @@ package io.fabienpuissant.fluent.builder.domain; - import io.fabienpuissant.fluent.builder.domain.outputcommand.BuilderCommandOutput; public interface BuilderPort { - void generateBuilder(BuilderCommandOutput commandOutput); + void generateBuilder(BuilderCommandOutput commandOutput); } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/domain/ExistingClass.java b/src/main/java/io/fabienpuissant/fluent/builder/domain/ExistingClass.java index a940e27..f8cdb57 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/domain/ExistingClass.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/domain/ExistingClass.java @@ -4,93 +4,92 @@ public class ExistingClass { - private final String className; - private final boolean isBuilderExist; - private final List builderInterfaces; - private final List classMethods; + private final String className; + private final boolean isBuilderExist; + private final List builderInterfaces; + private final List classMethods; - public String className() { - return className; - } + public String className() { + return className; + } - public boolean isBuilderExist() { - return isBuilderExist; - } + public boolean isBuilderExist() { + return isBuilderExist; + } - public List builderInterfaces() { - return builderInterfaces; - } + public List builderInterfaces() { + return builderInterfaces; + } - public List classMethods() { - return classMethods; - } + public List classMethods() { + return classMethods; + } - private ExistingClass(ExistingClassBuilder builder) { - assert builder.className != null && builder.builderInterfaces != null && builder.classMethods != null; + private ExistingClass(ExistingClassBuilder builder) { + assert builder.className != null && builder.builderInterfaces != null && builder.classMethods != null; - this.className = builder.className; - this.isBuilderExist = builder.isBuilderExist; - this.builderInterfaces = builder.builderInterfaces; - this.classMethods = builder.classMethods; - } - - public static ExistingClassNameBuilder builder() { - return new ExistingClassBuilder(); - } + this.className = builder.className; + this.isBuilderExist = builder.isBuilderExist; + this.builderInterfaces = builder.builderInterfaces; + this.classMethods = builder.classMethods; + } - public sealed interface ExistingClassNameBuilder permits ExistingClassBuilder { - IsBuilderExistBuilder className(String className); - } + public static ExistingClassNameBuilder builder() { + return new ExistingClassBuilder(); + } - public sealed interface IsBuilderExistBuilder permits ExistingClassBuilder { - ExistingClassInterfacesBuilder isBuilderExist(boolean isBuilderExist); - } + public sealed interface ExistingClassNameBuilder permits ExistingClassBuilder { + IsBuilderExistBuilder className(String className); + } - public sealed interface ExistingClassInterfacesBuilder permits ExistingClassBuilder { - ExistingClassMethodsBuilder interfaces(List builderInterfaces); - } + public sealed interface IsBuilderExistBuilder permits ExistingClassBuilder { + ExistingClassInterfacesBuilder isBuilderExist(boolean isBuilderExist); + } - public sealed interface ExistingClassMethodsBuilder permits ExistingClassBuilder { - ExistingClass classMethods(List classMethods); - } + public sealed interface ExistingClassInterfacesBuilder permits ExistingClassBuilder { + ExistingClassMethodsBuilder interfaces(List builderInterfaces); + } - private static final class ExistingClassBuilder implements ExistingClassNameBuilder, IsBuilderExistBuilder, ExistingClassInterfacesBuilder, ExistingClassMethodsBuilder { + public sealed interface ExistingClassMethodsBuilder permits ExistingClassBuilder { + ExistingClass classMethods(List classMethods); + } - private String className; - private boolean isBuilderExist; - private List builderInterfaces; - private List classMethods; + private static final class ExistingClassBuilder + implements ExistingClassNameBuilder, IsBuilderExistBuilder, ExistingClassInterfacesBuilder, ExistingClassMethodsBuilder { - private ExistingClassBuilder() { - } + private String className; + private boolean isBuilderExist; + private List builderInterfaces; + private List classMethods; - @Override - public IsBuilderExistBuilder className(String className) { - this.className = className; + private ExistingClassBuilder() {} - return this; - } + @Override + public IsBuilderExistBuilder className(String className) { + this.className = className; - @Override - public ExistingClassInterfacesBuilder isBuilderExist(boolean isBuilderExist) { - this.isBuilderExist = isBuilderExist; + return this; + } - return this; - } + @Override + public ExistingClassInterfacesBuilder isBuilderExist(boolean isBuilderExist) { + this.isBuilderExist = isBuilderExist; + return this; + } - @Override - public ExistingClassMethodsBuilder interfaces(List builderInterfaces) { - this.builderInterfaces = builderInterfaces; + @Override + public ExistingClassMethodsBuilder interfaces(List builderInterfaces) { + this.builderInterfaces = builderInterfaces; - return this; - } + return this; + } - @Override - public ExistingClass classMethods(List classMethods) { - this.classMethods = classMethods; + @Override + public ExistingClass classMethods(List classMethods) { + this.classMethods = classMethods; - return new ExistingClass(this); - } + return new ExistingClass(this); } -} \ No newline at end of file + } +} diff --git a/src/main/java/io/fabienpuissant/fluent/builder/domain/Field.java b/src/main/java/io/fabienpuissant/fluent/builder/domain/Field.java index 3b56d5a..14aa0c8 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/domain/Field.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/domain/Field.java @@ -1,69 +1,72 @@ package io.fabienpuissant.fluent.builder.domain; public class Field { - private final String name; - private final String type; - private final boolean isOptional; - public String name() { - return name; - } - public String type() { - return type; - } + private final String name; + private final String type; + private final boolean isOptional; - public boolean isOptional() { - return isOptional; - } + public String name() { + return name; + } - private Field(FieldBuilder builder) { - assert builder.name != null && builder.type != null; + public String type() { + return type; + } - this.name = builder.name; - this.type = builder.type; - this.isOptional = builder.isOptional; - } + public boolean isOptional() { + return isOptional; + } - public static FieldNameBuilder builder() { - return new FieldBuilder(); - } + private Field(FieldBuilder builder) { + assert builder.name != null && builder.type != null; - public sealed interface FieldNameBuilder permits FieldBuilder { - FieldTypeBuilder name(String name); - } + this.name = builder.name; + this.type = builder.type; + this.isOptional = builder.isOptional; + } - public sealed interface FieldTypeBuilder permits FieldBuilder { - FieldIsOptionalBuilder type(String type); - } + public static FieldNameBuilder builder() { + return new FieldBuilder(); + } - public sealed interface FieldIsOptionalBuilder permits FieldBuilder { - Field isOptional(boolean isOptional); - } + public sealed interface FieldNameBuilder permits FieldBuilder { + FieldTypeBuilder name(String name); + } + + public sealed interface FieldTypeBuilder permits FieldBuilder { + FieldIsOptionalBuilder type(String type); + } + + public sealed interface FieldIsOptionalBuilder permits FieldBuilder { + Field isOptional(boolean isOptional); + } - private static final class FieldBuilder implements FieldNameBuilder, FieldTypeBuilder, FieldIsOptionalBuilder { - private String name; - private String type; - private boolean isOptional; + private static final class FieldBuilder implements FieldNameBuilder, FieldTypeBuilder, FieldIsOptionalBuilder { - @Override - public FieldTypeBuilder name(String name) { - this.name = name; + private String name; + private String type; + private boolean isOptional; - return this; - } + @Override + public FieldTypeBuilder name(String name) { + this.name = name; - @Override - public FieldIsOptionalBuilder type(String type) { - this.type = type; + return this; + } + + @Override + public FieldIsOptionalBuilder type(String type) { + this.type = type; - return this; - } + return this; + } - @Override - public Field isOptional(boolean isOptional) { - this.isOptional = isOptional; + @Override + public Field isOptional(boolean isOptional) { + this.isOptional = isOptional; - return new Field(this); - } + return new Field(this); } + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/domain/Fields.java b/src/main/java/io/fabienpuissant/fluent/builder/domain/Fields.java index 66aadc0..f0aee6d 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/domain/Fields.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/domain/Fields.java @@ -4,11 +4,11 @@ import java.util.stream.Stream; public record Fields(List fields) { - public Fields { - assert fields != null; - } + public Fields { + assert fields != null; + } - public Fields concat(Fields newFields) { - return new Fields(Stream.concat(fields.stream(), newFields.fields().stream()).toList()); - } + public Fields concat(Fields newFields) { + return new Fields(Stream.concat(fields.stream(), newFields.fields().stream()).toList()); + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/domain/FluentBuilderParameters.java b/src/main/java/io/fabienpuissant/fluent/builder/domain/FluentBuilderParameters.java index 0d77d8e..4a44d17 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/domain/FluentBuilderParameters.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/domain/FluentBuilderParameters.java @@ -1,58 +1,55 @@ package io.fabienpuissant.fluent.builder.domain; public class FluentBuilderParameters { - private final ExistingClass existingClass; - private final Fields parameters; - public ExistingClass existingClass() { - return existingClass; - } + private final ExistingClass existingClass; + private final Fields parameters; - public static FluentBuilderParametersContextBuilder builder() { - return new FluentBuilderParametersBuilder(); - } + public ExistingClass existingClass() { + return existingClass; + } - public Fields parameters() { - return parameters; - } + public static FluentBuilderParametersContextBuilder builder() { + return new FluentBuilderParametersBuilder(); + } + public Fields parameters() { + return parameters; + } - private FluentBuilderParameters(FluentBuilderParametersBuilder builder) { - assert builder.context != null && builder.mandatoryParameters != null; - - existingClass = builder.context; - parameters = builder.mandatoryParameters; - } + private FluentBuilderParameters(FluentBuilderParametersBuilder builder) { + assert builder.context != null && builder.mandatoryParameters != null; - private static final class FluentBuilderParametersBuilder implements - FluentBuilderParametersContextBuilder, - FluentBuilderParametersMandatoryParametersBuilder { - private ExistingClass context; - private Fields mandatoryParameters; + existingClass = builder.context; + parameters = builder.mandatoryParameters; + } + private static final class FluentBuilderParametersBuilder + implements FluentBuilderParametersContextBuilder, FluentBuilderParametersMandatoryParametersBuilder { - @Override - public FluentBuilderParametersMandatoryParametersBuilder context(ExistingClass context) { - this.context = context; + private ExistingClass context; + private Fields mandatoryParameters; - return this; - } + @Override + public FluentBuilderParametersMandatoryParametersBuilder context(ExistingClass context) { + this.context = context; - @Override - public FluentBuilderParameters parameters(Fields mandatoryParameters) { - this.mandatoryParameters = mandatoryParameters; - - return new FluentBuilderParameters(this); - - } + return this; } - public sealed interface FluentBuilderParametersContextBuilder permits FluentBuilderParametersBuilder { - FluentBuilderParametersMandatoryParametersBuilder context(ExistingClass context); - } + @Override + public FluentBuilderParameters parameters(Fields mandatoryParameters) { + this.mandatoryParameters = mandatoryParameters; - public sealed interface FluentBuilderParametersMandatoryParametersBuilder permits FluentBuilderParametersBuilder { - FluentBuilderParameters parameters(Fields mandatoryParameters); + return new FluentBuilderParameters(this); } + } + + public sealed interface FluentBuilderParametersContextBuilder permits FluentBuilderParametersBuilder { + FluentBuilderParametersMandatoryParametersBuilder context(ExistingClass context); + } + public sealed interface FluentBuilderParametersMandatoryParametersBuilder permits FluentBuilderParametersBuilder { + FluentBuilderParameters parameters(Fields mandatoryParameters); + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/domain/Interface.java b/src/main/java/io/fabienpuissant/fluent/builder/domain/Interface.java index e72a21d..e4e6961 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/domain/Interface.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/domain/Interface.java @@ -4,56 +4,55 @@ public class Interface { - private final String name; - private final List signatures; + private final String name; + private final List signatures; - public String name() { - return name; - } + public String name() { + return name; + } - public List signatures() { - return signatures; - } + public List signatures() { + return signatures; + } - private Interface(InterfaceBuilder builder) { - assert builder.name != null && builder.signatures != null; + private Interface(InterfaceBuilder builder) { + assert builder.name != null && builder.signatures != null; - this.name = builder.name; - this.signatures = builder.signatures; - } + this.name = builder.name; + this.signatures = builder.signatures; + } - public static InterfaceSignatureBuilder builder() { - return new InterfaceBuilder(); - } + public static InterfaceSignatureBuilder builder() { + return new InterfaceBuilder(); + } - public sealed interface InterfaceSignatureBuilder permits InterfaceBuilder { - InterfaceContentBuilder name(final String name); - } + public sealed interface InterfaceSignatureBuilder permits InterfaceBuilder { + InterfaceContentBuilder name(final String name); + } - public sealed interface InterfaceContentBuilder permits InterfaceBuilder { - Interface signatures(final List signatures); - } + public sealed interface InterfaceContentBuilder permits InterfaceBuilder { + Interface signatures(final List signatures); + } - private static final class InterfaceBuilder implements InterfaceSignatureBuilder, InterfaceContentBuilder { + private static final class InterfaceBuilder implements InterfaceSignatureBuilder, InterfaceContentBuilder { - private String name; - private List signatures; + private String name; + private List signatures; - private InterfaceBuilder() { - } + private InterfaceBuilder() {} - @Override - public InterfaceContentBuilder name(final String name) { - this.name = name; + @Override + public InterfaceContentBuilder name(final String name) { + this.name = name; - return this; - } + return this; + } - @Override - public Interface signatures(final List signatures) { - this.signatures = signatures; + @Override + public Interface signatures(final List signatures) { + this.signatures = signatures; - return new Interface(this); - } + return new Interface(this); } + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/domain/Method.java b/src/main/java/io/fabienpuissant/fluent/builder/domain/Method.java index d02505b..425259f 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/domain/Method.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/domain/Method.java @@ -2,56 +2,55 @@ public class Method { - private final String signature; - private final String content; + private final String signature; + private final String content; - public String signature() { - return signature; - } + public String signature() { + return signature; + } - public String content() { - return content; - } + public String content() { + return content; + } - private Method(MethodBuilder builder) { - assert builder.signature != null && builder.content != null; + private Method(MethodBuilder builder) { + assert builder.signature != null && builder.content != null; - this.signature = builder.signature; - this.content = builder.content; - } + this.signature = builder.signature; + this.content = builder.content; + } - public static MethodSignatureBuilder builder() { - return new MethodBuilder(); - } + public static MethodSignatureBuilder builder() { + return new MethodBuilder(); + } - public sealed interface MethodSignatureBuilder permits MethodBuilder { - MethodContentBuilder signature(final String signature); - } + public sealed interface MethodSignatureBuilder permits MethodBuilder { + MethodContentBuilder signature(final String signature); + } - public sealed interface MethodContentBuilder permits MethodBuilder { - Method content(final String content); - } + public sealed interface MethodContentBuilder permits MethodBuilder { + Method content(final String content); + } - public static final class MethodBuilder implements MethodSignatureBuilder, MethodContentBuilder { + public static final class MethodBuilder implements MethodSignatureBuilder, MethodContentBuilder { - private String signature; - private String content; + private String signature; + private String content; - private MethodBuilder() { - } + private MethodBuilder() {} - @Override - public MethodContentBuilder signature(final String signature) { - this.signature = signature; + @Override + public MethodContentBuilder signature(final String signature) { + this.signature = signature; - return this; - } + return this; + } - @Override - public Method content(final String content) { - this.content = content; + @Override + public Method content(final String content) { + this.content = content; - return new Method(this); - } + return new Method(this); } -} \ No newline at end of file + } +} diff --git a/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/BuilderCommand.java b/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/BuilderCommand.java index 2875ae2..4ddfe5c 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/BuilderCommand.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/BuilderCommand.java @@ -1,9 +1,7 @@ package io.fabienpuissant.fluent.builder.domain.outputcommand; public interface BuilderCommand { + CommandScope scope(); - CommandScope scope(); - - TargetType type(); - + TargetType type(); } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/BuilderCommandOutput.java b/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/BuilderCommandOutput.java index 97a7f89..7dbd167 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/BuilderCommandOutput.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/BuilderCommandOutput.java @@ -1,8 +1,5 @@ package io.fabienpuissant.fluent.builder.domain.outputcommand; - import java.util.List; -public record BuilderCommandOutput(List commands) { - -} +public record BuilderCommandOutput(List commands) {} diff --git a/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/CommandContent.java b/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/CommandContent.java index b06e874..4e53834 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/CommandContent.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/CommandContent.java @@ -1,40 +1,37 @@ package io.fabienpuissant.fluent.builder.domain.outputcommand; - import java.util.Objects; import java.util.Optional; public class CommandContent { - private final String value; + private final String value; - public CommandContent(String value) { - this.value = value; - } + public CommandContent(String value) { + this.value = value; + } - public Optional value() { - if (value == null) return Optional.empty(); + public Optional value() { + if (value == null) return Optional.empty(); - return Optional.of(value); - } + return Optional.of(value); + } - @Override - public boolean equals(Object o) { - if (o == null || getClass() != o.getClass()) return false; + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; - CommandContent that = (CommandContent) o; - return Objects.equals(value, that.value); - } + CommandContent that = (CommandContent) o; + return Objects.equals(value, that.value); + } - @Override - public int hashCode() { - return Objects.hashCode(value); - } + @Override + public int hashCode() { + return Objects.hashCode(value); + } - @Override - public String toString() { - return "CommandContent{" + - "value='" + value + '\'' + - '}'; - } + @Override + public String toString() { + return "CommandContent{" + "value='" + value + '\'' + '}'; + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/CommandScope.java b/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/CommandScope.java index 7822446..f576da3 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/CommandScope.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/CommandScope.java @@ -1,6 +1,6 @@ package io.fabienpuissant.fluent.builder.domain.outputcommand; public enum CommandScope { - CLASS, - BUILDER + CLASS, + BUILDER, } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/CommandSignature.java b/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/CommandSignature.java index 8f964d1..f383b3e 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/CommandSignature.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/CommandSignature.java @@ -1,7 +1,7 @@ package io.fabienpuissant.fluent.builder.domain.outputcommand; public record CommandSignature(String value) { - public CommandSignature { - assert value != null; - } + public CommandSignature { + assert value != null; + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/CreateCommand.java b/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/CreateCommand.java index a424214..9490cc3 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/CreateCommand.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/CreateCommand.java @@ -3,121 +3,116 @@ import java.util.Objects; public class CreateCommand implements BuilderCommand { - private final CommandSignature signature; - private final CommandContent content; - private final CommandScope scope; - private final TargetType type; - @Override - public CommandScope scope() { - return scope; - } - - public CommandContent content() { - return content; - } - - public CommandSignature signature() { - return signature; - } - - @Override - public TargetType type() { - return type; - } - - private CreateCommand(CreateCommandBuilder builder) { - assert builder.signature != null && builder.scope != null && builder.content != null && builder.type != null; - - this.signature = builder.signature; - this.content = builder.content; - this.scope = builder.scope; - this.type = builder.type; - } + private final CommandSignature signature; + private final CommandContent content; + private final CommandScope scope; + private final TargetType type; - public static CommandSignatureBuilder builder() { - return new CreateCommandBuilder(); - } + @Override + public CommandScope scope() { + return scope; + } - public sealed interface CommandSignatureBuilder permits CreateCommandBuilder { - CommandContentBuilder signature(CommandSignature signature); - } + public CommandContent content() { + return content; + } - public sealed interface CommandContentBuilder permits CreateCommandBuilder { - CommandScopeBuilder content(CommandContent content); - } + public CommandSignature signature() { + return signature; + } - public sealed interface CommandScopeBuilder permits CreateCommandBuilder { - CreateCommandTypeBuilder scope(CommandScope scope); - } + @Override + public TargetType type() { + return type; + } - public sealed interface CreateCommandTypeBuilder permits CreateCommandBuilder { - CreateCommand type(TargetType type); - } + private CreateCommand(CreateCommandBuilder builder) { + assert builder.signature != null && builder.scope != null && builder.content != null && builder.type != null; + this.signature = builder.signature; + this.content = builder.content; + this.scope = builder.scope; + this.type = builder.type; + } - private static final class CreateCommandBuilder implements - CommandContentBuilder, CommandSignatureBuilder, CommandScopeBuilder, CreateCommandTypeBuilder { + public static CommandSignatureBuilder builder() { + return new CreateCommandBuilder(); + } - private CommandSignature signature; - private CommandContent content; - private CommandScope scope; - private TargetType type; + public sealed interface CommandSignatureBuilder permits CreateCommandBuilder { + CommandContentBuilder signature(CommandSignature signature); + } + public sealed interface CommandContentBuilder permits CreateCommandBuilder { + CommandScopeBuilder content(CommandContent content); + } - @Override - public CommandContentBuilder signature(CommandSignature signature) { - assert signature != null; + public sealed interface CommandScopeBuilder permits CreateCommandBuilder { + CreateCommandTypeBuilder scope(CommandScope scope); + } - this.signature = signature; + public sealed interface CreateCommandTypeBuilder permits CreateCommandBuilder { + CreateCommand type(TargetType type); + } - return this; - } + private static final class CreateCommandBuilder + implements CommandContentBuilder, CommandSignatureBuilder, CommandScopeBuilder, CreateCommandTypeBuilder { - @Override - public CommandScopeBuilder content(CommandContent content) { - this.content = content; + private CommandSignature signature; + private CommandContent content; + private CommandScope scope; + private TargetType type; - return this; - } - - @Override - public CreateCommandTypeBuilder scope(CommandScope scope) { - this.scope = scope; - - return this; - } + @Override + public CommandContentBuilder signature(CommandSignature signature) { + assert signature != null; - @Override - public CreateCommand type(TargetType type) { - this.type = type; + this.signature = signature; - return new CreateCommand(this); - } + return this; } @Override - public boolean equals(Object o) { - if (o == null || getClass() != o.getClass()) return false; + public CommandScopeBuilder content(CommandContent content) { + this.content = content; - CreateCommand that = (CreateCommand) o; - return signature.equals(that.signature) && Objects.equals(content, that.content) && scope == that.scope; + return this; } @Override - public int hashCode() { - int result = signature.hashCode(); - result = 31 * result + Objects.hashCode(content); - result = 31 * result + scope.hashCode(); - return result; + public CreateCommandTypeBuilder scope(CommandScope scope) { + this.scope = scope; + + return this; } @Override - public String toString() { - return "CreateCommand{" + - "signature=" + signature + - ", content=" + content + - ", scope=" + scope + - '}'; + public CreateCommand type(TargetType type) { + this.type = type; + + return new CreateCommand(this); } + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + + CreateCommand that = (CreateCommand) o; + return signature.equals(that.signature) && Objects.equals(content, that.content) && scope == that.scope; + } + + @Override + public int hashCode() { + int result = signature.hashCode(); + result = 31 * result + Objects.hashCode(content); + result = 31 * result + scope.hashCode(); + return result; + } + + @Override + public String toString() { + return "CreateCommand{" + "signature=" + signature + ", content=" + content + ", scope=" + scope + '}'; + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/DeleteCommand.java b/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/DeleteCommand.java index 804d6a9..783d8bf 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/DeleteCommand.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/DeleteCommand.java @@ -4,98 +4,95 @@ public class DeleteCommand implements BuilderCommand { - private final TargetName name; - private final CommandScope scope; - private final TargetType type; + private final TargetName name; + private final CommandScope scope; + private final TargetType type; - public TargetName name() { - return name; - } + public TargetName name() { + return name; + } - @Override - public CommandScope scope() { - return scope; - } + @Override + public CommandScope scope() { + return scope; + } - @Override - public TargetType type() { - return type; - } + @Override + public TargetType type() { + return type; + } - private DeleteCommand(DeleteCommandBuilder builder) { - assert builder.name != null && builder.scope != null && builder.type != null; + private DeleteCommand(DeleteCommandBuilder builder) { + assert builder.name != null && builder.scope != null && builder.type != null; - this.name = builder.name; - this.scope = builder.scope; - this.type = builder.type; - } + this.name = builder.name; + this.scope = builder.scope; + this.type = builder.type; + } - public static DeleteCommandTargetNameBuilder builder() { - return new DeleteCommandBuilder(); - } + public static DeleteCommandTargetNameBuilder builder() { + return new DeleteCommandBuilder(); + } - public sealed interface DeleteCommandTargetNameBuilder permits DeleteCommandBuilder { - DeleteCommandScopeBuilder name(TargetName name); - } + public sealed interface DeleteCommandTargetNameBuilder permits DeleteCommandBuilder { + DeleteCommandScopeBuilder name(TargetName name); + } - public sealed interface DeleteCommandScopeBuilder permits DeleteCommandBuilder { - DeleteCommandTypeBuilder scope(CommandScope scope); - } + public sealed interface DeleteCommandScopeBuilder permits DeleteCommandBuilder { + DeleteCommandTypeBuilder scope(CommandScope scope); + } - public sealed interface DeleteCommandTypeBuilder permits DeleteCommandBuilder { - DeleteCommand type(TargetType type); - } - - private static final class DeleteCommandBuilder implements DeleteCommandTargetNameBuilder, DeleteCommandScopeBuilder, DeleteCommandTypeBuilder { - - private TargetName name; - private CommandScope scope; - private TargetType type; - - @Override - public DeleteCommandScopeBuilder name(TargetName name) { - this.name = name; + public sealed interface DeleteCommandTypeBuilder permits DeleteCommandBuilder { + DeleteCommand type(TargetType type); + } - return this; - } + private static final class DeleteCommandBuilder + implements DeleteCommandTargetNameBuilder, DeleteCommandScopeBuilder, DeleteCommandTypeBuilder { - @Override - public DeleteCommandTypeBuilder scope(CommandScope scope) { - this.scope = scope; + private TargetName name; + private CommandScope scope; + private TargetType type; - return this; - } - - @Override - public DeleteCommand type(TargetType type) { - this.type = type; + @Override + public DeleteCommandScopeBuilder name(TargetName name) { + this.name = name; - return new DeleteCommand(this); - } + return this; } @Override - public boolean equals(Object o) { - if (o == null || getClass() != o.getClass()) return false; + public DeleteCommandTypeBuilder scope(CommandScope scope) { + this.scope = scope; - DeleteCommand that = (DeleteCommand) o; - return Objects.equals(name, that.name) && scope == that.scope && type == that.type; + return this; } @Override - public int hashCode() { - int result = Objects.hashCode(name); - result = 31 * result + Objects.hashCode(scope); - result = 31 * result + Objects.hashCode(type); - return result; - } + public DeleteCommand type(TargetType type) { + this.type = type; - @Override - public String toString() { - return "DeleteCommand{" + - "name=" + name + - ", scope=" + scope + - ", type=" + type + - '}'; + return new DeleteCommand(this); } + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + + DeleteCommand that = (DeleteCommand) o; + return Objects.equals(name, that.name) && scope == that.scope && type == that.type; + } + + @Override + public int hashCode() { + int result = Objects.hashCode(name); + result = 31 * result + Objects.hashCode(scope); + result = 31 * result + Objects.hashCode(type); + return result; + } + + @Override + public String toString() { + return "DeleteCommand{" + "name=" + name + ", scope=" + scope + ", type=" + type + '}'; + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/TargetName.java b/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/TargetName.java index b9195bd..b6eff55 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/TargetName.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/TargetName.java @@ -1,8 +1,7 @@ package io.fabienpuissant.fluent.builder.domain.outputcommand; public record TargetName(String name) { - - public TargetName { - assert name != null; - } + public TargetName { + assert name != null; + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/TargetType.java b/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/TargetType.java index 4887a3a..05563dc 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/TargetType.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/domain/outputcommand/TargetType.java @@ -1,9 +1,9 @@ package io.fabienpuissant.fluent.builder.domain.outputcommand; public enum TargetType { - FIELD, - METHOD, - INTERFACE, - CLASS, - CONSTRUCTOR + FIELD, + METHOD, + INTERFACE, + CLASS, + CONSTRUCTOR, } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/icons/FluentBuilderIcon.java b/src/main/java/io/fabienpuissant/fluent/builder/icons/FluentBuilderIcon.java index 8cdf241..3d73b70 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/icons/FluentBuilderIcon.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/icons/FluentBuilderIcon.java @@ -1,10 +1,9 @@ package io.fabienpuissant.fluent.builder.icons; import com.intellij.openapi.util.IconLoader; - import javax.swing.*; public interface FluentBuilderIcon { - Icon MoveUp = IconLoader.getIcon("/icons/moveUp.svg", FluentBuilderIcon.class); - Icon MoveDown = IconLoader.getIcon("/icons/moveDown.svg", FluentBuilderIcon.class); -} \ No newline at end of file + Icon MoveUp = IconLoader.getIcon("/icons/moveUp.svg", FluentBuilderIcon.class); + Icon MoveDown = IconLoader.getIcon("/icons/moveDown.svg", FluentBuilderIcon.class); +} diff --git a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/primary/DialogFieldArrangement.java b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/primary/DialogFieldArrangement.java index edb5cac..ec434e9 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/primary/DialogFieldArrangement.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/primary/DialogFieldArrangement.java @@ -1,7 +1,7 @@ package io.fabienpuissant.fluent.builder.infrastructure.primary; -import io.fabienpuissant.fluent.builder.application.FluentBuilderApplicationService; -import io.fabienpuissant.fluent.builder.icons.FluentBuilderIcon; +import static com.intellij.ui.ToolbarDecorator.createDecorator; + import com.intellij.ide.util.DefaultPsiElementCellRenderer; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -9,14 +9,13 @@ import com.intellij.psi.PsiField; import com.intellij.ui.ToolbarDecorator; import com.intellij.ui.components.JBList; -import org.jetbrains.annotations.NotNull; - -import javax.swing.*; +import io.fabienpuissant.fluent.builder.application.FluentBuilderApplicationService; +import io.fabienpuissant.fluent.builder.icons.FluentBuilderIcon; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; - -import static com.intellij.ui.ToolbarDecorator.createDecorator; +import javax.swing.*; +import org.jetbrains.annotations.NotNull; /** * Credit ... @@ -24,114 +23,116 @@ public class DialogFieldArrangement extends DialogWrapper { - final PluginContext context; - private final JBList fieldList; - private final JBList optionalFieldList; - private final DefaultListModel fieldListModel; - private final DefaultListModel optionalFieldListModel; - private final FluentBuilderApplicationService builder = new FluentBuilderApplicationService(); - - public DialogFieldArrangement(final PluginContext context, DefaultListModel fields) { - super(context.ownerClass().getProject()); - this.context = context; - - - setSize(600, 800); - setTitle(Message.SELECT_OPTIONAL_FIELDS.label()); - - fieldListModel = fields; - optionalFieldListModel = new DefaultListModel<>(); - fieldList = createPsiFieldList(fieldListModel); - optionalFieldList = createPsiFieldList(optionalFieldListModel); - init(); - } - - private JBList createPsiFieldList(final DefaultListModel fieldListModel) { - final JBList fieldList = new JBList<>(fieldListModel); - fieldList.setCellRenderer(new DefaultPsiElementCellRenderer()); - fieldList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); - return fieldList; - } - - @Override - protected void init() { - super.init(); - } - - private Box createLeftAlignedBoxWithText(String text) { - Box box = Box.createHorizontalBox(); - box.add(new JLabel(text, SwingConstants.LEFT)); - box.add(Box.createHorizontalGlue()); - return box; - } - - @Override - protected JComponent createCenterPanel() { - JPanel panel = new JPanel(); - panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); - - panel.add(createLeftAlignedBoxWithText(Message.REQUIRED_FIELDS.label())); - panel.add(Box.createVerticalStrut(10)); - - panel.add(createToolbar(fieldList) - .addExtraAction(new AnAction(Message.MOVE_DOWN.label(), Message.MOVE_DOWN.label(), FluentBuilderIcon.MoveDown) { - @Override - public void actionPerformed(@NotNull AnActionEvent e) { - moveFields(fieldList, fieldListModel, optionalFieldListModel); - } - }).createPanel()); - - panel.add(Box.createVerticalStrut(10)); - panel.add(createLeftAlignedBoxWithText(Message.OPTIONAL_FIELDS.label())); - panel.add(Box.createVerticalStrut(10)); - - panel.add(createToolbar(optionalFieldList) - .addExtraAction(new AnAction(Message.MOVE_UP.label(), Message.MOVE_UP.label(), FluentBuilderIcon.MoveUp) { - @Override - public void actionPerformed(@NotNull AnActionEvent e) { - moveFields(optionalFieldList, optionalFieldListModel, fieldListModel); - } - }).createPanel()); - - return panel; - } - - private ToolbarDecorator createToolbar(JList fieldList) { - return createDecorator(fieldList) - .disableAddAction() - .disableRemoveAction(); - } - - @Override - protected void doOKAction() { - List selectedFields = getFields(); - - super.doOKAction(); - builder.generateBuilder(context, selectedFields, getOptionalFields()); - } - - private void moveFields(JList sourceList, DefaultListModel sourceModel, DefaultListModel targetModel) { - List selectedFields = sourceList.getSelectedValuesList(); - selectedFields.stream() - .filter(field -> !targetModel.contains(field)) - .forEach(targetModel::addElement); - - selectedFields.forEach(sourceModel::removeElement); - } - - private List getSelectedFieldsFromList(JList list) { - ListModel model = list.getModel(); - return IntStream.range(0, model.getSize()) - .mapToObj(model::getElementAt) - .collect(Collectors.toList()); - } - - private List getFields() { - return getSelectedFieldsFromList(fieldList); - } - - private List getOptionalFields() { - return getSelectedFieldsFromList(optionalFieldList); - } - + final PluginContext context; + private final JBList fieldList; + private final JBList optionalFieldList; + private final DefaultListModel fieldListModel; + private final DefaultListModel optionalFieldListModel; + private final FluentBuilderApplicationService builder = new FluentBuilderApplicationService(); + + public DialogFieldArrangement(final PluginContext context, DefaultListModel fields) { + super(context.ownerClass().getProject()); + this.context = context; + + setSize(600, 800); + setTitle(Message.SELECT_OPTIONAL_FIELDS.label()); + + fieldListModel = fields; + optionalFieldListModel = new DefaultListModel<>(); + fieldList = createPsiFieldList(fieldListModel); + optionalFieldList = createPsiFieldList(optionalFieldListModel); + init(); + } + + private JBList createPsiFieldList(final DefaultListModel fieldListModel) { + final JBList fieldList = new JBList<>(fieldListModel); + fieldList.setCellRenderer(new DefaultPsiElementCellRenderer()); + fieldList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + return fieldList; + } + + @Override + protected void init() { + super.init(); + } + + private Box createLeftAlignedBoxWithText(String text) { + Box box = Box.createHorizontalBox(); + box.add(new JLabel(text, SwingConstants.LEFT)); + box.add(Box.createHorizontalGlue()); + return box; + } + + @Override + protected JComponent createCenterPanel() { + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + + panel.add(createLeftAlignedBoxWithText(Message.REQUIRED_FIELDS.label())); + panel.add(Box.createVerticalStrut(10)); + + panel.add( + createToolbar(fieldList) + .addExtraAction( + new AnAction(Message.MOVE_DOWN.label(), Message.MOVE_DOWN.label(), FluentBuilderIcon.MoveDown) { + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + moveFields(fieldList, fieldListModel, optionalFieldListModel); + } + } + ) + .createPanel() + ); + + panel.add(Box.createVerticalStrut(10)); + panel.add(createLeftAlignedBoxWithText(Message.OPTIONAL_FIELDS.label())); + panel.add(Box.createVerticalStrut(10)); + + panel.add( + createToolbar(optionalFieldList) + .addExtraAction( + new AnAction(Message.MOVE_UP.label(), Message.MOVE_UP.label(), FluentBuilderIcon.MoveUp) { + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + moveFields(optionalFieldList, optionalFieldListModel, fieldListModel); + } + } + ) + .createPanel() + ); + + return panel; + } + + private ToolbarDecorator createToolbar(JList fieldList) { + return createDecorator(fieldList).disableAddAction().disableRemoveAction(); + } + + @Override + protected void doOKAction() { + List selectedFields = getFields(); + + super.doOKAction(); + builder.generateBuilder(context, selectedFields, getOptionalFields()); + } + + private void moveFields(JList sourceList, DefaultListModel sourceModel, DefaultListModel targetModel) { + List selectedFields = sourceList.getSelectedValuesList(); + selectedFields.stream().filter(field -> !targetModel.contains(field)).forEach(targetModel::addElement); + + selectedFields.forEach(sourceModel::removeElement); + } + + private List getSelectedFieldsFromList(JList list) { + ListModel model = list.getModel(); + return IntStream.range(0, model.getSize()).mapToObj(model::getElementAt).collect(Collectors.toList()); + } + + private List getFields() { + return getSelectedFieldsFromList(fieldList); + } + + private List getOptionalFields() { + return getSelectedFieldsFromList(optionalFieldList); + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/primary/DialogFieldSelection.java b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/primary/DialogFieldSelection.java index 9b5d397..229a9e5 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/primary/DialogFieldSelection.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/primary/DialogFieldSelection.java @@ -1,5 +1,8 @@ package io.fabienpuissant.fluent.builder.infrastructure.primary; +import static com.intellij.openapi.ui.LabeledComponent.create; +import static com.intellij.ui.ToolbarDecorator.createDecorator; + import com.intellij.ide.util.DefaultPsiElementCellRenderer; import com.intellij.lang.jvm.JvmModifier; import com.intellij.openapi.ui.DialogWrapper; @@ -8,13 +11,8 @@ import com.intellij.ui.CollectionListModel; import com.intellij.ui.ToolbarDecorator; import com.intellij.ui.components.JBList; - -import javax.swing.*; - import java.util.Arrays; - -import static com.intellij.openapi.ui.LabeledComponent.create; -import static com.intellij.ui.ToolbarDecorator.createDecorator; +import javax.swing.*; /** * Credit ... @@ -22,66 +20,61 @@ public class DialogFieldSelection extends DialogWrapper { - final PluginContext context; - private final JBList fieldList; - - public DialogFieldSelection(final PluginContext context) { - super(context.ownerClass().getProject()); - - this.context = context; - fieldList = loadClassFields(context.ownerClass()); - selectAllFields(); - setSize(600, 400); - setTitle(Message.SELECT_FIELDS.label()); - init(); - } - - @Override - protected void init() { - super.init(); + final PluginContext context; + private final JBList fieldList; + + public DialogFieldSelection(final PluginContext context) { + super(context.ownerClass().getProject()); + this.context = context; + fieldList = loadClassFields(context.ownerClass()); + selectAllFields(); + setSize(600, 400); + setTitle(Message.SELECT_FIELDS.label()); + init(); + } + + @Override + protected void init() { + super.init(); + } + + private void selectAllFields() { + int[] indices = new int[fieldList.getModel().getSize()]; + for (int i = 0; i < indices.length; i++) { + indices[i] = i; } - - private void selectAllFields() { - int[] indices = new int[fieldList.getModel().getSize()]; - for (int i = 0; i < indices.length; i++) { - indices[i] = i; - } - fieldList.setSelectedIndices(indices); - } - - private JBList loadClassFields(final PsiClass ownerClass) { - CollectionListModel fields = new CollectionListModel<>(Arrays.stream(ownerClass.getFields()).filter( - psiField -> !psiField.hasModifier(JvmModifier.STATIC) - ).toList()); - JBList fieldsList = new JBList<>(fields); - fieldsList.setCellRenderer(new DefaultPsiElementCellRenderer()); - return fieldsList; - } - - private ToolbarDecorator createToolbar() { - return createDecorator(fieldList) - .disableAddAction() - .disableRemoveAction() - .disableUpDownActions(); - } - - @Override - protected void doOKAction() { - DefaultListModel selectedFields = getFields(); - - super.doOKAction(); - new DialogFieldArrangement(context, selectedFields).show(); - } - - @Override - protected JComponent createCenterPanel() { - return create(createToolbar().createPanel(), Message.FIELDS_SELECTION_TITLE.label()); - } - - public DefaultListModel getFields() { - DefaultListModel model = new DefaultListModel<>(); - fieldList.getSelectedValuesList().forEach(model::addElement); - return model; - } - + fieldList.setSelectedIndices(indices); + } + + private JBList loadClassFields(final PsiClass ownerClass) { + CollectionListModel fields = new CollectionListModel<>( + Arrays.stream(ownerClass.getFields()).filter(psiField -> !psiField.hasModifier(JvmModifier.STATIC)).toList() + ); + JBList fieldsList = new JBList<>(fields); + fieldsList.setCellRenderer(new DefaultPsiElementCellRenderer()); + return fieldsList; + } + + private ToolbarDecorator createToolbar() { + return createDecorator(fieldList).disableAddAction().disableRemoveAction().disableUpDownActions(); + } + + @Override + protected void doOKAction() { + DefaultListModel selectedFields = getFields(); + + super.doOKAction(); + new DialogFieldArrangement(context, selectedFields).show(); + } + + @Override + protected JComponent createCenterPanel() { + return create(createToolbar().createPanel(), Message.FIELDS_SELECTION_TITLE.label()); + } + + public DefaultListModel getFields() { + DefaultListModel model = new DefaultListModel<>(); + fieldList.getSelectedValuesList().forEach(model::addElement); + return model; + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/primary/FluentBuilderAction.java b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/primary/FluentBuilderAction.java index 474e32b..fe4f5eb 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/primary/FluentBuilderAction.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/primary/FluentBuilderAction.java @@ -1,6 +1,5 @@ package io.fabienpuissant.fluent.builder.infrastructure.primary; -import io.fabienpuissant.fluent.builder.infrastructure.secondary.PsiClassService; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.PlatformDataKeys; @@ -11,33 +10,34 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; +import io.fabienpuissant.fluent.builder.infrastructure.secondary.PsiClassService; public class FluentBuilderAction extends AnAction { - private final PsiClassService psiClassService; - - public FluentBuilderAction() { - this.psiClassService = ApplicationManager.getApplication().getService(PsiClassService.class); - } + private final PsiClassService psiClassService; - @Override - public void actionPerformed(AnActionEvent event) { - Project project = event.getProject(); - Editor editor = event.getData(PlatformDataKeys.EDITOR); + public FluentBuilderAction() { + this.psiClassService = ApplicationManager.getApplication().getService(PsiClassService.class); + } - if (project == null || editor == null) { - return; - } + @Override + public void actionPerformed(AnActionEvent event) { + Project project = event.getProject(); + Editor editor = event.getData(PlatformDataKeys.EDITOR); - PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); - PsiClass psiClass = PsiTreeUtil.findChildOfType(psiFile, PsiClass.class); + if (project == null || editor == null) { + return; + } - if (psiClass == null) { - return; - } - psiClassService.setPsiClass(psiClass); + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + PsiClass psiClass = PsiTreeUtil.findChildOfType(psiFile, PsiClass.class); - DialogFieldSelection dialog = new DialogFieldSelection(new PluginContext(project, editor, psiClass)); - dialog.show(); + if (psiClass == null) { + return; } + psiClassService.setPsiClass(psiClass); + + DialogFieldSelection dialog = new DialogFieldSelection(new PluginContext(project, editor, psiClass)); + dialog.show(); + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/primary/FluentBuilderParametersMapper.java b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/primary/FluentBuilderParametersMapper.java index 68d0181..beb6cd9 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/primary/FluentBuilderParametersMapper.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/primary/FluentBuilderParametersMapper.java @@ -2,156 +2,144 @@ import com.intellij.psi.*; import io.fabienpuissant.fluent.builder.domain.*; -import org.jetbrains.annotations.Nullable; - import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.jetbrains.annotations.Nullable; public class FluentBuilderParametersMapper { - private FluentBuilderParametersMapper() {} - - - public static FluentBuilderParameters toDomain(PluginContext context, List mandatoryFields, List optionalFields) { - return FluentBuilderParameters.builder() - .context(mapContext(context)) - .parameters(mapFields(mandatoryFields, false).concat(mapFields(optionalFields, true))); - } - - private static Fields mapFields(List fields, boolean isOptional) { - return new Fields( - fields.stream().map(field -> Field.builder() - .name(field.getName()) - .type(field.getType().getPresentableText()) - .isOptional(isOptional)).toList() - ); - } + private FluentBuilderParametersMapper() {} + + public static FluentBuilderParameters toDomain(PluginContext context, List mandatoryFields, List optionalFields) { + return FluentBuilderParameters.builder() + .context(mapContext(context)) + .parameters(mapFields(mandatoryFields, false).concat(mapFields(optionalFields, true))); + } + + private static Fields mapFields(List fields, boolean isOptional) { + return new Fields( + fields + .stream() + .map(field -> Field.builder().name(field.getName()).type(field.getType().getPresentableText()).isOptional(isOptional)) + .toList() + ); + } + + private static ExistingClass mapContext(PluginContext context) { + PsiClass psiClass = context.ownerClass(); + return ExistingClass.builder() + .className(context.ownerClass().getName()) + .isBuilderExist(isBuilderExist(psiClass)) + .interfaces(getInterfaces(psiClass)) + .classMethods(extractMethods(psiClass)); + } + + private static List getInterfaces(PsiClass psiClass) { + return extractInterfaces(psiClass).stream().map(FluentBuilderParametersMapper::mapInterface).toList(); + } + + private static Interface mapInterface(PsiClass psiClass) { + return Interface.builder().name(psiClass.getName()).signatures(extractInterfaceSignature(psiClass)); + } + + private static boolean isBuilderExist(PsiClass psiClass) { + return getBuilder(psiClass) != null; + } + + private static String builderName(String className) { + return className + "Builder"; + } + + private static @Nullable PsiClass getBuilder(PsiClass psiClass) { + return psiClass.findInnerClassByName(builderName(psiClass.getName()), false); + } + + private static List extractInterfaces(PsiClass psiClass) { + return Arrays.stream(psiClass.getInnerClasses()).filter(PsiClass::isInterface).toList(); + } + + private static List extractInterfaceSignature(PsiClass psiClass) { + List methodSignatures = new ArrayList<>(); + + for (PsiMethod method : psiClass.getMethods()) { + StringBuilder signatureBuilder = new StringBuilder(); + + // Add return type + PsiType returnType = method.getReturnType(); + if (returnType != null) { + signatureBuilder.append(returnType.getCanonicalText()).append(" "); + } + + // Add method name + signatureBuilder.append(method.getName()).append("("); + + // Add parameters + PsiParameter[] parameters = method.getParameterList().getParameters(); + for (int i = 0; i < parameters.length; i++) { + PsiParameter parameter = parameters[i]; + signatureBuilder.append(parameter.getType().getCanonicalText()).append(" ").append(parameter.getName()); + if (i < parameters.length - 1) { + signatureBuilder.append(", "); + } + } - private static ExistingClass mapContext(PluginContext context) { - PsiClass psiClass = context.ownerClass(); - return ExistingClass.builder() - .className(context.ownerClass().getName()) - .isBuilderExist(isBuilderExist(psiClass)) - .interfaces(getInterfaces(psiClass)) - .classMethods(extractMethods(psiClass)); - } + signatureBuilder.append(");"); - private static List getInterfaces(PsiClass psiClass) { - return extractInterfaces(psiClass).stream().map(FluentBuilderParametersMapper::mapInterface).toList(); + methodSignatures.add(signatureBuilder.toString()); } - private static Interface mapInterface(PsiClass psiClass) { - return Interface.builder().name(psiClass.getName()).signatures(extractInterfaceSignature(psiClass)); - } + return methodSignatures; + } - private static boolean isBuilderExist(PsiClass psiClass) { - return getBuilder(psiClass) != null; - } + public static List extractMethods(PsiClass psiClass) { + List methods = new ArrayList<>(); - private static String builderName(String className) { - return className + "Builder"; - } - - private static @Nullable PsiClass getBuilder(PsiClass psiClass) { - return psiClass.findInnerClassByName(builderName(psiClass.getName()), false); - } + if (psiClass != null) { + for (PsiMethod psiMethod : psiClass.getMethods()) { + String signature = buildMethodSignature(psiMethod); + String content = extractMethodContent(psiMethod); - private static List extractInterfaces(PsiClass psiClass) { - return Arrays.stream(psiClass.getInnerClasses()) - .filter(PsiClass::isInterface) - .toList(); + // Build and add the Method instance + methods.add(Method.builder().signature(signature).content(content)); + } } - private static List extractInterfaceSignature(PsiClass psiClass) { - List methodSignatures = new ArrayList<>(); + return methods; + } - for (PsiMethod method : psiClass.getMethods()) { - StringBuilder signatureBuilder = new StringBuilder(); + private static String buildMethodSignature(PsiMethod psiMethod) { + StringBuilder signatureBuilder = new StringBuilder(); - // Add return type - PsiType returnType = method.getReturnType(); - if (returnType != null) { - signatureBuilder.append(returnType.getCanonicalText()).append(" "); - } - - // Add method name - signatureBuilder.append(method.getName()).append("("); - - // Add parameters - PsiParameter[] parameters = method.getParameterList().getParameters(); - for (int i = 0; i < parameters.length; i++) { - PsiParameter parameter = parameters[i]; - signatureBuilder.append(parameter.getType().getCanonicalText()) - .append(" ") - .append(parameter.getName()); - if (i < parameters.length - 1) { - signatureBuilder.append(", "); - } - } - - signatureBuilder.append(");"); - - methodSignatures.add(signatureBuilder.toString()); - } - - return methodSignatures; + // Add return type + PsiType returnType = psiMethod.getReturnType(); + if (returnType != null) { + signatureBuilder.append(returnType.getCanonicalText()).append(" "); } - public static List extractMethods(PsiClass psiClass) { - List methods = new ArrayList<>(); - - if (psiClass != null) { - for (PsiMethod psiMethod : psiClass.getMethods()) { - String signature = buildMethodSignature(psiMethod); - String content = extractMethodContent(psiMethod); - - // Build and add the Method instance - methods.add( - Method.builder() - .signature(signature) - .content(content) - ); - } - } - - return methods; + // Add method name + signatureBuilder.append(psiMethod.getName()).append("("); + + // Add parameters + PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); + for (int i = 0; i < parameters.length; i++) { + PsiParameter parameter = parameters[i]; + signatureBuilder.append(parameter.getType().getCanonicalText()).append(" ").append(parameter.getName()); + if (i < parameters.length - 1) { + signatureBuilder.append(", "); + } } - private static String buildMethodSignature(PsiMethod psiMethod) { - StringBuilder signatureBuilder = new StringBuilder(); + signatureBuilder.append(");"); + return signatureBuilder.toString(); + } - // Add return type - PsiType returnType = psiMethod.getReturnType(); - if (returnType != null) { - signatureBuilder.append(returnType.getCanonicalText()).append(" "); - } - - // Add method name - signatureBuilder.append(psiMethod.getName()).append("("); - - // Add parameters - PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); - for (int i = 0; i < parameters.length; i++) { - PsiParameter parameter = parameters[i]; - signatureBuilder.append(parameter.getType().getCanonicalText()) - .append(" ") - .append(parameter.getName()); - if (i < parameters.length - 1) { - signatureBuilder.append(", "); - } - } - - signatureBuilder.append(");"); - return signatureBuilder.toString(); - } - - private static String extractMethodContent(PsiMethod psiMethod) { - PsiCodeBlock body = psiMethod.getBody(); - if (body != null) { - String bodyText = body.getText(); - return bodyText.substring(1, bodyText.length() - 1).trim(); - } - return ""; + private static String extractMethodContent(PsiMethod psiMethod) { + PsiCodeBlock body = psiMethod.getBody(); + if (body != null) { + String bodyText = body.getText(); + return bodyText.substring(1, bodyText.length() - 1).trim(); } + return ""; + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/primary/Message.java b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/primary/Message.java index 597c1b5..8c0f601 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/primary/Message.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/primary/Message.java @@ -1,22 +1,21 @@ package io.fabienpuissant.fluent.builder.infrastructure.primary; public enum Message { - SELECT_FIELDS("Select Fields"), - FIELDS_SELECTION_TITLE("Select fields for the Sealed Fluent Builder (optional fields can be explicitly selected later)"), - SELECT_OPTIONAL_FIELDS("Select Optional Fields (the Order Is Respected by the Builder)"), - REQUIRED_FIELDS("Required fields:"), - OPTIONAL_FIELDS("Optional fields:"), - MOVE_DOWN("Move Down"), - MOVE_UP("Move UP"); + SELECT_FIELDS("Select Fields"), + FIELDS_SELECTION_TITLE("Select fields for the Sealed Fluent Builder (optional fields can be explicitly selected later)"), + SELECT_OPTIONAL_FIELDS("Select Optional Fields (the Order Is Respected by the Builder)"), + REQUIRED_FIELDS("Required fields:"), + OPTIONAL_FIELDS("Optional fields:"), + MOVE_DOWN("Move Down"), + MOVE_UP("Move UP"); + private final String label; - private final String label; + Message(String label) { + this.label = label; + } - Message(String label) { - this.label = label; - } - - public String label() { - return label; - } + public String label() { + return label; + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/FluentBuilderGenerator.java b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/FluentBuilderGenerator.java index cafd388..bce3d58 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/FluentBuilderGenerator.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/FluentBuilderGenerator.java @@ -1,85 +1,82 @@ package io.fabienpuissant.fluent.builder.infrastructure.secondary; -import io.fabienpuissant.fluent.builder.domain.BuilderPort; -import io.fabienpuissant.fluent.builder.domain.outputcommand.*; -import io.fabienpuissant.fluent.builder.infrastructure.secondary.commands.CommandHandler; -import io.fabienpuissant.fluent.builder.infrastructure.secondary.commands.CommandHandlerRegistry; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.psi.PsiClass; import com.intellij.psi.codeStyle.CodeStyleManager; +import io.fabienpuissant.fluent.builder.domain.BuilderPort; +import io.fabienpuissant.fluent.builder.domain.outputcommand.*; +import io.fabienpuissant.fluent.builder.infrastructure.secondary.commands.CommandHandler; +import io.fabienpuissant.fluent.builder.infrastructure.secondary.commands.CommandHandlerRegistry; public class FluentBuilderGenerator implements BuilderPort { - private final PsiClass psiClass; - - public FluentBuilderGenerator() { - PsiClassService psiClassService = ApplicationManager.getApplication().getService(PsiClassService.class); - psiClass = psiClassService.getPsiClass().orElseThrow(); - } + private final PsiClass psiClass; + public FluentBuilderGenerator() { + PsiClassService psiClassService = ApplicationManager.getApplication().getService(PsiClassService.class); + psiClass = psiClassService.getPsiClass().orElseThrow(); + } - @Override - public void generateBuilder(BuilderCommandOutput commandOutput) { - for (BuilderCommand command : commandOutput.commands()) { - if (command instanceof CreateCommand createCommand) { - WriteCommandAction.runWriteCommandAction(psiClass.getProject(), () -> { - executeCreateCommand(createCommand); - }); - } else if (command instanceof DeleteCommand deleteCommand) { - WriteCommandAction.runWriteCommandAction(psiClass.getProject(), () -> { - executeDeleteCommand(deleteCommand); - }); - } else { - throw new UnsupportedOperationException("Unsupported command type: " + command.getClass().getName()); - } - } + @Override + public void generateBuilder(BuilderCommandOutput commandOutput) { + for (BuilderCommand command : commandOutput.commands()) { + if (command instanceof CreateCommand createCommand) { WriteCommandAction.runWriteCommandAction(psiClass.getProject(), () -> { - CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(psiClass.getProject()); - codeStyleManager.reformat(psiClass); + executeCreateCommand(createCommand); }); + } else if (command instanceof DeleteCommand deleteCommand) { + WriteCommandAction.runWriteCommandAction(psiClass.getProject(), () -> { + executeDeleteCommand(deleteCommand); + }); + } else { + throw new UnsupportedOperationException("Unsupported command type: " + command.getClass().getName()); + } } + WriteCommandAction.runWriteCommandAction(psiClass.getProject(), () -> { + CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(psiClass.getProject()); + codeStyleManager.reformat(psiClass); + }); + } - private void executeCreateCommand(CreateCommand createCommand) { - PsiClass targetClass = getTargetClass(createCommand); + private void executeCreateCommand(CreateCommand createCommand) { + PsiClass targetClass = getTargetClass(createCommand); - TargetType type = createCommand.type(); - CommandHandler handler = new CommandHandlerRegistry().getHandler(type); + TargetType type = createCommand.type(); + CommandHandler handler = new CommandHandlerRegistry().getHandler(type); - if (handler != null) { - handler.handle(targetClass, createCommand); - } else { - throw new UnsupportedOperationException("No handler found for type: " + type); - } + if (handler != null) { + handler.handle(targetClass, createCommand); + } else { + throw new UnsupportedOperationException("No handler found for type: " + type); } + } - private void executeDeleteCommand(DeleteCommand deleteCommand) { - PsiClass targetClass = getTargetClass(deleteCommand); + private void executeDeleteCommand(DeleteCommand deleteCommand) { + PsiClass targetClass = getTargetClass(deleteCommand); - TargetType type = deleteCommand.type(); - CommandHandler handler = new CommandHandlerRegistry().getHandler(type); + TargetType type = deleteCommand.type(); + CommandHandler handler = new CommandHandlerRegistry().getHandler(type); - if (handler != null) { - handler.handle(targetClass, deleteCommand); - } else { - throw new UnsupportedOperationException("No handler found for type: " + type); - } + if (handler != null) { + handler.handle(targetClass, deleteCommand); + } else { + throw new UnsupportedOperationException("No handler found for type: " + type); } + } - private PsiClass getTargetClass(BuilderCommand command) { - PsiClass targetClass = (command.scope() == CommandScope.BUILDER) - ? getBuilderClass() - : psiClass; + private PsiClass getTargetClass(BuilderCommand command) { + PsiClass targetClass = (command.scope() == CommandScope.BUILDER) ? getBuilderClass() : psiClass; - if (targetClass == null) { - throw new IllegalArgumentException("Target class is null. Cannot add elements."); - } - return targetClass; + if (targetClass == null) { + throw new IllegalArgumentException("Target class is null. Cannot add elements."); } + return targetClass; + } - private PsiClass getBuilderClass() { - PsiClass builderClass = psiClass.findInnerClassByName("%sBuilder".formatted(psiClass.getName()), false); - assert builderClass != null; - return builderClass; - } + private PsiClass getBuilderClass() { + PsiClass builderClass = psiClass.findInnerClassByName("%sBuilder".formatted(psiClass.getName()), false); + assert builderClass != null; + return builderClass; + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/PsiClassService.java b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/PsiClassService.java index 577148c..9f28057 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/PsiClassService.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/PsiClassService.java @@ -1,12 +1,10 @@ package io.fabienpuissant.fluent.builder.infrastructure.secondary; import com.intellij.psi.PsiClass; - import java.util.Optional; public interface PsiClassService { + Optional getPsiClass(); - Optional getPsiClass(); - - void setPsiClass(PsiClass psiClass); + void setPsiClass(PsiClass psiClass); } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/PsiClassServiceImpl.java b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/PsiClassServiceImpl.java index 3d73dec..494969b 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/PsiClassServiceImpl.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/PsiClassServiceImpl.java @@ -2,23 +2,21 @@ import com.intellij.openapi.components.Service; import com.intellij.psi.PsiClass; - - import java.util.Optional; @Service public final class PsiClassServiceImpl implements PsiClassService { - private PsiClass psiClass; - @Override - public Optional getPsiClass() { - if (psiClass == null) return Optional.empty(); - return Optional.of(psiClass); - } + private PsiClass psiClass; - @Override - public void setPsiClass(PsiClass psiClass) { - this.psiClass = psiClass; - } -} + @Override + public Optional getPsiClass() { + if (psiClass == null) return Optional.empty(); + return Optional.of(psiClass); + } + @Override + public void setPsiClass(PsiClass psiClass) { + this.psiClass = psiClass; + } +} diff --git a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/ClassCommandHandler.java b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/ClassCommandHandler.java index 0049938..b34f9c7 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/ClassCommandHandler.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/ClassCommandHandler.java @@ -1,27 +1,27 @@ package io.fabienpuissant.fluent.builder.infrastructure.secondary.commands; -import io.fabienpuissant.fluent.builder.domain.outputcommand.CreateCommand; -import io.fabienpuissant.fluent.builder.domain.outputcommand.DeleteCommand; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElementFactory; +import io.fabienpuissant.fluent.builder.domain.outputcommand.CreateCommand; +import io.fabienpuissant.fluent.builder.domain.outputcommand.DeleteCommand; public class ClassCommandHandler extends CommandHandler { - @Override - public void handle(PsiClass targetClass, CreateCommand command) { - String signature = command.signature().value(); - String content = command.content().value().orElse(""); - PsiElementFactory factory = JavaPsiFacade.getElementFactory(psiClass.getProject()); - String methodText = "\t" + signature + " {\n" + content + "\n}"; - PsiClass newClass = factory.createImplicitClassFromText(methodText, targetClass); - targetClass.add(newClass); - } + @Override + public void handle(PsiClass targetClass, CreateCommand command) { + String signature = command.signature().value(); + String content = command.content().value().orElse(""); + PsiElementFactory factory = JavaPsiFacade.getElementFactory(psiClass.getProject()); + String methodText = "\t" + signature + " {\n" + content + "\n}"; + PsiClass newClass = factory.createImplicitClassFromText(methodText, targetClass); + targetClass.add(newClass); + } - @Override - public void handle(PsiClass targetClass, DeleteCommand command) { - PsiClass innerClassByName = targetClass.findInnerClassByName(command.name().name(), false); - assert innerClassByName != null; - innerClassByName.delete(); - } + @Override + public void handle(PsiClass targetClass, DeleteCommand command) { + PsiClass innerClassByName = targetClass.findInnerClassByName(command.name().name(), false); + assert innerClassByName != null; + innerClassByName.delete(); + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/CommandHandler.java b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/CommandHandler.java index f0800cc..df3ae74 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/CommandHandler.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/CommandHandler.java @@ -1,21 +1,21 @@ package io.fabienpuissant.fluent.builder.infrastructure.secondary.commands; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.psi.PsiClass; import io.fabienpuissant.fluent.builder.domain.outputcommand.CreateCommand; import io.fabienpuissant.fluent.builder.domain.outputcommand.DeleteCommand; import io.fabienpuissant.fluent.builder.infrastructure.secondary.PsiClassService; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.psi.PsiClass; public abstract class CommandHandler { - protected final PsiClass psiClass; + protected final PsiClass psiClass; - public CommandHandler() { - PsiClassService psiClassService = ApplicationManager.getApplication().getService(PsiClassService.class); - psiClass = psiClassService.getPsiClass().orElseThrow(); - } + public CommandHandler() { + PsiClassService psiClassService = ApplicationManager.getApplication().getService(PsiClassService.class); + psiClass = psiClassService.getPsiClass().orElseThrow(); + } - public abstract void handle(PsiClass targetClass, CreateCommand command); + public abstract void handle(PsiClass targetClass, CreateCommand command); - public abstract void handle(PsiClass targetClass, DeleteCommand command); + public abstract void handle(PsiClass targetClass, DeleteCommand command); } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/CommandHandlerRegistry.java b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/CommandHandlerRegistry.java index b96f470..82b5dbd 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/CommandHandlerRegistry.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/CommandHandlerRegistry.java @@ -1,22 +1,22 @@ package io.fabienpuissant.fluent.builder.infrastructure.secondary.commands; import io.fabienpuissant.fluent.builder.domain.outputcommand.TargetType; - import java.util.HashMap; import java.util.Map; public class CommandHandlerRegistry { - private final Map handlers = new HashMap<>(); - public CommandHandlerRegistry() { - handlers.put(TargetType.FIELD, new FieldCommandHandler()); - handlers.put(TargetType.METHOD, new MethodCommandHandler()); - handlers.put(TargetType.CONSTRUCTOR, new ConstructorCommandHandler()); - handlers.put(TargetType.INTERFACE, new InterfaceCommandHandler()); - handlers.put(TargetType.CLASS, new ClassCommandHandler()); - } + private final Map handlers = new HashMap<>(); + + public CommandHandlerRegistry() { + handlers.put(TargetType.FIELD, new FieldCommandHandler()); + handlers.put(TargetType.METHOD, new MethodCommandHandler()); + handlers.put(TargetType.CONSTRUCTOR, new ConstructorCommandHandler()); + handlers.put(TargetType.INTERFACE, new InterfaceCommandHandler()); + handlers.put(TargetType.CLASS, new ClassCommandHandler()); + } - public CommandHandler getHandler(TargetType commandType) { - return handlers.get(commandType); - } + public CommandHandler getHandler(TargetType commandType) { + return handlers.get(commandType); + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/ConstructorCommandHandler.java b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/ConstructorCommandHandler.java index c5c095a..ffbaedb 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/ConstructorCommandHandler.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/ConstructorCommandHandler.java @@ -1,33 +1,33 @@ package io.fabienpuissant.fluent.builder.infrastructure.secondary.commands; +import com.intellij.psi.*; import io.fabienpuissant.fluent.builder.domain.outputcommand.CreateCommand; import io.fabienpuissant.fluent.builder.domain.outputcommand.DeleteCommand; -import com.intellij.psi.*; - import java.util.Arrays; import java.util.Objects; class ConstructorCommandHandler extends CommandHandler { - @Override - public void handle(PsiClass targetClass, CreateCommand command) { - String signature = command.signature().value(); - String content = command.content().value().orElse(""); - PsiElementFactory factory = JavaPsiFacade.getElementFactory(psiClass.getProject()); - String constructorText = signature + " {\n" + content + "\n}"; - PsiMethod constructor = factory.createMethodFromText(constructorText, targetClass); - if (constructor.isConstructor()) { - targetClass.add(constructor); - } else { - throw new IllegalArgumentException("Invalid constructor signature: " + signature); - } + @Override + public void handle(PsiClass targetClass, CreateCommand command) { + String signature = command.signature().value(); + String content = command.content().value().orElse(""); + PsiElementFactory factory = JavaPsiFacade.getElementFactory(psiClass.getProject()); + String constructorText = signature + " {\n" + content + "\n}"; + PsiMethod constructor = factory.createMethodFromText(constructorText, targetClass); + if (constructor.isConstructor()) { + targetClass.add(constructor); + } else { + throw new IllegalArgumentException("Invalid constructor signature: " + signature); } + } - @Override - public void handle(PsiClass targetClass, DeleteCommand command) { - PsiMethod[] constructors = targetClass.getConstructors(); - Arrays.stream(constructors).filter(Objects::nonNull) - .filter(constructor -> Objects.requireNonNull(constructor.getSignature(PsiSubstitutor.EMPTY).toString()).contains("Builder")) - .forEach(PsiElement::delete); - } + @Override + public void handle(PsiClass targetClass, DeleteCommand command) { + PsiMethod[] constructors = targetClass.getConstructors(); + Arrays.stream(constructors) + .filter(Objects::nonNull) + .filter(constructor -> Objects.requireNonNull(constructor.getSignature(PsiSubstitutor.EMPTY).toString()).contains("Builder")) + .forEach(PsiElement::delete); + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/FieldCommandHandler.java b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/FieldCommandHandler.java index 4c68e50..7038569 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/FieldCommandHandler.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/FieldCommandHandler.java @@ -1,26 +1,26 @@ package io.fabienpuissant.fluent.builder.infrastructure.secondary.commands; -import io.fabienpuissant.fluent.builder.domain.outputcommand.CreateCommand; -import io.fabienpuissant.fluent.builder.domain.outputcommand.DeleteCommand; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElementFactory; import com.intellij.psi.PsiField; +import io.fabienpuissant.fluent.builder.domain.outputcommand.CreateCommand; +import io.fabienpuissant.fluent.builder.domain.outputcommand.DeleteCommand; class FieldCommandHandler extends CommandHandler { - @Override - public void handle(PsiClass targetClass, CreateCommand command) { - String signature = command.signature().value(); - PsiElementFactory factory = JavaPsiFacade.getElementFactory(psiClass.getProject()); - PsiField field = factory.createFieldFromText(signature, targetClass); - targetClass.add(field); - } + @Override + public void handle(PsiClass targetClass, CreateCommand command) { + String signature = command.signature().value(); + PsiElementFactory factory = JavaPsiFacade.getElementFactory(psiClass.getProject()); + PsiField field = factory.createFieldFromText(signature, targetClass); + targetClass.add(field); + } - @Override - public void handle(PsiClass targetClass, DeleteCommand command) { - PsiField psiField = targetClass.findFieldByName(command.name().name(), false); - assert psiField != null; - psiField.delete(); - } + @Override + public void handle(PsiClass targetClass, DeleteCommand command) { + PsiField psiField = targetClass.findFieldByName(command.name().name(), false); + assert psiField != null; + psiField.delete(); + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/InterfaceCommandHandler.java b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/InterfaceCommandHandler.java index 437a883..864e054 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/InterfaceCommandHandler.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/InterfaceCommandHandler.java @@ -1,38 +1,38 @@ package io.fabienpuissant.fluent.builder.infrastructure.secondary.commands; -import io.fabienpuissant.fluent.builder.domain.outputcommand.CreateCommand; -import io.fabienpuissant.fluent.builder.domain.outputcommand.DeleteCommand; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElementFactory; +import io.fabienpuissant.fluent.builder.domain.outputcommand.CreateCommand; +import io.fabienpuissant.fluent.builder.domain.outputcommand.DeleteCommand; public class InterfaceCommandHandler extends CommandHandler { - @Override - public void handle(PsiClass targetClass, CreateCommand command) { - String signature = command.signature().value(); - String content = command.content().value().orElse(""); - PsiElementFactory factory = JavaPsiFacade.getElementFactory(psiClass.getProject()); + @Override + public void handle(PsiClass targetClass, CreateCommand command) { + String signature = command.signature().value(); + String content = command.content().value().orElse(""); + PsiElementFactory factory = JavaPsiFacade.getElementFactory(psiClass.getProject()); - String interfaceText = signature + " { " + content + " }"; + String interfaceText = signature + " { " + content + " }"; - PsiClass dummyClass = factory.createClassFromText(interfaceText, null); + PsiClass dummyClass = factory.createClassFromText(interfaceText, null); - PsiClass[] innerClasses = dummyClass.getInnerClasses(); - for (PsiClass inner : innerClasses) { - if (inner.isInterface()) { - targetClass.add(inner); - return; - } - } - - throw new IllegalArgumentException("Failed to create interface from signature: " + signature); + PsiClass[] innerClasses = dummyClass.getInnerClasses(); + for (PsiClass inner : innerClasses) { + if (inner.isInterface()) { + targetClass.add(inner); + return; + } } - @Override - public void handle(PsiClass targetClass, DeleteCommand command) { - PsiClass innerClassByName = psiClass.findInnerClassByName(command.name().name(), false); - assert innerClassByName != null; - innerClassByName.delete(); - } + throw new IllegalArgumentException("Failed to create interface from signature: " + signature); + } + + @Override + public void handle(PsiClass targetClass, DeleteCommand command) { + PsiClass innerClassByName = psiClass.findInnerClassByName(command.name().name(), false); + assert innerClassByName != null; + innerClassByName.delete(); + } } diff --git a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/MethodCommandHandler.java b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/MethodCommandHandler.java index 37bbb1c..66dda62 100644 --- a/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/MethodCommandHandler.java +++ b/src/main/java/io/fabienpuissant/fluent/builder/infrastructure/secondary/commands/MethodCommandHandler.java @@ -1,27 +1,26 @@ package io.fabienpuissant.fluent.builder.infrastructure.secondary.commands; +import com.intellij.psi.*; import io.fabienpuissant.fluent.builder.domain.outputcommand.CreateCommand; import io.fabienpuissant.fluent.builder.domain.outputcommand.DeleteCommand; -import com.intellij.psi.*; - import java.util.Arrays; import java.util.Objects; public class MethodCommandHandler extends CommandHandler { - @Override - public void handle(PsiClass targetClass, CreateCommand command) { - String signature = command.signature().value(); - String content = command.content().value().orElse(""); - PsiElementFactory factory = JavaPsiFacade.getElementFactory(psiClass.getProject()); - String methodText = signature + " {\n" + content + "\n}"; - PsiMethod method = factory.createMethodFromText(methodText, targetClass); - targetClass.add(method); - } + @Override + public void handle(PsiClass targetClass, CreateCommand command) { + String signature = command.signature().value(); + String content = command.content().value().orElse(""); + PsiElementFactory factory = JavaPsiFacade.getElementFactory(psiClass.getProject()); + String methodText = signature + " {\n" + content + "\n}"; + PsiMethod method = factory.createMethodFromText(methodText, targetClass); + targetClass.add(method); + } - @Override - public void handle(PsiClass targetClass, DeleteCommand command) { - PsiMethod[] psiMethods = psiClass.findMethodsByName(command.name().name(), false); - Arrays.stream(psiMethods).filter(Objects::nonNull).forEach(PsiElement::delete); - } + @Override + public void handle(PsiClass targetClass, DeleteCommand command) { + PsiMethod[] psiMethods = psiClass.findMethodsByName(command.name().name(), false); + Arrays.stream(psiMethods).filter(Objects::nonNull).forEach(PsiElement::delete); + } } diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 9e8e9ce..fdaa3d3 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -1,21 +1,22 @@ - - com.fluent.builder.fluent-builder + + com.fluent.builder.fluent-builder - 1.0.1 + 1.0.1 - - Fluent Builder + Fluent Builder - - Fabien Puissant + + Fabien Puissant - -

The IntelliJ Fluent Builder Plugin is your go-to solution for generating and managing fluent builders in Java projects.

@@ -45,27 +46,31 @@ ]]>
- - com.intellij.modules.platform - com.intellij.modules.java + com.intellij.modules.platform + com.intellij.modules.java - - - - + + + - com.intellij.java + com.intellij.java - - - - - - - -
\ No newline at end of file + + + + + + + diff --git a/src/main/resources/META-INF/pluginIcon.svg b/src/main/resources/META-INF/pluginIcon.svg index 8312e07..d279987 100644 --- a/src/main/resources/META-INF/pluginIcon.svg +++ b/src/main/resources/META-INF/pluginIcon.svg @@ -1,8 +1,13 @@ - - - - - + + + + + - diff --git a/src/main/resources/icons/moveDown.svg b/src/main/resources/icons/moveDown.svg index 33660bf..ad9b2e8 100644 --- a/src/main/resources/icons/moveDown.svg +++ b/src/main/resources/icons/moveDown.svg @@ -1,9 +1,14 @@ - - - - - - + + + + + + diff --git a/src/main/resources/icons/moveUp.svg b/src/main/resources/icons/moveUp.svg index 61c8854..4dac062 100644 --- a/src/main/resources/icons/moveUp.svg +++ b/src/main/resources/icons/moveUp.svg @@ -1,8 +1,13 @@ - - - - - - - \ No newline at end of file + + + + + + + diff --git a/src/test/io/fabienpuissant/fluent/builder/BuilderIT.java b/src/test/io/fabienpuissant/fluent/builder/BuilderIT.java new file mode 100644 index 0000000..e6c0b95 --- /dev/null +++ b/src/test/io/fabienpuissant/fluent/builder/BuilderIT.java @@ -0,0 +1,9 @@ +package io.fabienpuissant.fluent.builder; + +import org.junit.jupiter.api.Test; + +class BuilderIT { + + @Test + void there_for_ci() {} +} diff --git a/src/test/io/fabienpuissant/fluent/builder/domain/BuilderGeneratorDomainServiceTest.java b/src/test/io/fabienpuissant/fluent/builder/domain/BuilderGeneratorDomainServiceTest.java index 1f9954e..0c80b68 100644 --- a/src/test/io/fabienpuissant/fluent/builder/domain/BuilderGeneratorDomainServiceTest.java +++ b/src/test/io/fabienpuissant/fluent/builder/domain/BuilderGeneratorDomainServiceTest.java @@ -1,8 +1,12 @@ package io.fabienpuissant.fluent.builder.domain; +import static io.fabienpuissant.fluent.builder.domain.FluentBuilderFixtures.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.verify; import io.fabienpuissant.fluent.builder.domain.outputcommand.*; import io.fabienpuissant.fluent.builder.infrastructure.secondary.FluentBuilderGenerator; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -11,358 +15,406 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.List; - -import static io.fabienpuissant.fluent.builder.domain.FluentBuilderFixtures.*; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.verify; - @ExtendWith(MockitoExtension.class) class BuilderGeneratorDomainServiceTest { - @Mock - private FluentBuilderGenerator builderPort; - - private BuilderGeneratorDomainService builder; - - @Captor - private ArgumentCaptor commandOutput; - - @BeforeEach - void setUp() { - this.builder = new BuilderGeneratorDomainService(builderPort); - } - - @Test - void shouldDeleteOneInterfaces() { - builder.generateBuilder(classWithOneInterface()); - - verify(builderPort).generateBuilder(commandOutput.capture()); - assertThat(commandOutput.getValue().commands()).contains( - DeleteCommand.builder() - .name(new TargetName("SutNameBuilder")) - .scope(CommandScope.CLASS) - .type(TargetType.INTERFACE) - - ); - } - - @Test - void shouldRemoveAllCurrentInterfaces() { - builder.generateBuilder(classWithInterfaces()); - - verify(builderPort).generateBuilder(commandOutput.capture()); - assertThat(commandOutput.getValue().commands()).contains( - DeleteCommand.builder() - .name(new TargetName("SutNameBuilder")) - .scope(CommandScope.CLASS) - .type(TargetType.INTERFACE) - - ).contains( - DeleteCommand.builder() - .name(new TargetName("SutTypeBuilder")) - .scope(CommandScope.CLASS) - .type(TargetType.INTERFACE) - ); - } - - @Test - void shouldCreateLastInterfaceReturnBuiltObject() { - builder.generateBuilder(classWithOneMandatoryParameter()); - - verify(builderPort).generateBuilder(commandOutput.capture()); - assertThat(commandOutput.getValue().commands()).contains( - CreateCommand.builder() - .signature(new CommandSignature("public sealed interface SutFirstNameBuilder permits SutBuilder")) - .content(new CommandContent("Sut firstName(String firstName);")) - .scope(CommandScope.CLASS) - .type(TargetType.INTERFACE) - ); - } - - @Test - void shouldInterfaceImplementNextMandatoryParamInterface() { - builder.generateBuilder(classWithTwoMandatoryParameter()); - - verify(builderPort).generateBuilder(commandOutput.capture()); - assertThat(commandOutput.getValue().commands()).contains( - CreateCommand.builder() - .signature(new CommandSignature("public sealed interface SutFirstNameBuilder permits SutBuilder")) - .content(new CommandContent("SutLastNameBuilder firstName(String firstName);")) - .scope(CommandScope.CLASS) - .type(TargetType.INTERFACE) - ).contains(CreateCommand.builder() - .signature(new CommandSignature("public sealed interface SutLastNameBuilder permits SutBuilder")) - .content(new CommandContent("Sut lastName(String lastName);")) - .scope(CommandScope.CLASS) - .type(TargetType.INTERFACE)); - } - - @Test - void shouldAddOptionalParamInterfaceAtTheEnd() { - builder.generateBuilder(classWithTwoMandatoryParameterAndOneOptional()); - - verify(builderPort).generateBuilder(commandOutput.capture()); - assertThat(commandOutput.getValue().commands()).contains( - CreateCommand.builder() - .signature(new CommandSignature("public sealed interface SutOptionalBuilder permits SutBuilder")) - .content(new CommandContent("SutOptionalBuilder age(int age);\nSut build();")) - .scope(CommandScope.CLASS) - .type(TargetType.INTERFACE) - ); - } - - @Test - void shouldOptionalParamBeInOptionalBuilder() { - builder.generateBuilder(classWithTwoMandatoryParameterAndTwoOptional()); - - verify(builderPort).generateBuilder(commandOutput.capture()); - assertThat(commandOutput.getValue().commands()).contains( - CreateCommand.builder() - .signature(new CommandSignature("public sealed interface SutLastNameBuilder permits SutBuilder")) - .content(new CommandContent("SutOptionalBuilder lastName(String lastName);")) - .scope(CommandScope.CLASS) - .type(TargetType.INTERFACE)) - .contains( - CreateCommand.builder() - .signature(new CommandSignature("public sealed interface SutOptionalBuilder permits SutBuilder")) - .content(new CommandContent("SutOptionalBuilder age(int age);\nSutOptionalBuilder gender(String gender);\nSut build();")) - .scope(CommandScope.CLASS) - .type(TargetType.INTERFACE)); - } - - @Test - void shouldCreateBuilder() { - builder.generateBuilder(emptyClass()); - - verify(builderPort).generateBuilder(commandOutput.capture()); - assertThat(commandOutput.getValue().commands()).contains( - CreateCommand.builder() - .signature(new CommandSignature("private static final class SutBuilder implements SutFirstNameBuilder")) - .content(new CommandContent(null)) - .scope(CommandScope.CLASS) - .type(TargetType.CLASS)); - } - - @Test - void shouldDropAndCreateCreateBuilderIfAlreadyExists() { - builder.generateBuilder(emptyClassWithBuilder()); - - verify(builderPort).generateBuilder(commandOutput.capture()); - assertThat(commandOutput.getValue().commands()).containsSequence(List.of( - DeleteCommand.builder() - .name(new TargetName("SutBuilder")) - .scope(CommandScope.CLASS) - .type(TargetType.CLASS), - CreateCommand.builder() - .signature(new CommandSignature("private static final class SutBuilder implements SutFirstNameBuilder")) - .content(new CommandContent(null)) - .scope(CommandScope.CLASS) - .type(TargetType.CLASS))); - } - - @Test - void shouldCreateBuilderImplementsAllInterfaces() { - builder.generateBuilder(classWithTwoMandatoryParameter()); - - verify(builderPort).generateBuilder(commandOutput.capture()); - assertThat(commandOutput.getValue().commands()).contains( - CreateCommand.builder() - .signature(new CommandSignature("private static final class SutBuilder implements SutFirstNameBuilder, SutLastNameBuilder")) - .content(new CommandContent(null)) - .scope(CommandScope.CLASS) - .type(TargetType.CLASS)); - } - - @Test - void shouldCreateBuilderImplementsAllInterfacesWithOptional() { - builder.generateBuilder(classWithTwoMandatoryParameterAndOneOptional()); - - verify(builderPort).generateBuilder(commandOutput.capture()); - assertThat(commandOutput.getValue().commands()).contains( - CreateCommand.builder() - .signature(new CommandSignature("private static final class SutBuilder implements SutFirstNameBuilder, SutLastNameBuilder, SutOptionalBuilder")) - .content(new CommandContent(null)) - .scope(CommandScope.CLASS) - .type(TargetType.CLASS)); - } - - @Test - void shouldCreateBuilderFieldsWhenNotExists() { - builder.generateBuilder(classWithOneMandatoryParameter()); - - verify(builderPort).generateBuilder(commandOutput.capture()); - assertThat(commandOutput.getValue().commands()).contains( - CreateCommand.builder() - .signature(new CommandSignature("private String firstName;")) - .content(new CommandContent(null)) - .scope(CommandScope.BUILDER) - .type(TargetType.FIELD)); - } - - @Test - void shouldNotAlterBuilderFieldWhenExistInCurrentBuilder() { - builder.generateBuilder(classWithBuilderFieldExistingInParams()); - - verify(builderPort).generateBuilder(commandOutput.capture()); - assertThat(commandOutput.getValue().commands()).noneSatisfy(command -> { - assertThat(command).isInstanceOfSatisfying(CreateCommand.class, create -> { - assertThat(create.scope()).isEqualTo(CommandScope.BUILDER); - assertThat(create.signature().value()).contains("firstName").contains("lastName"); - }).isInstanceOfSatisfying(DeleteCommand.class, delete -> { - assertThat(delete.name()).isEqualTo("firstName").isEqualTo("lastName"); - }); + @Mock + private FluentBuilderGenerator builderPort; + + private BuilderGeneratorDomainService builder; + + @Captor + private ArgumentCaptor commandOutput; + + @BeforeEach + void setUp() { + this.builder = new BuilderGeneratorDomainService(builderPort); + } + + @Test + void shouldDeleteOneInterfaces() { + builder.generateBuilder(classWithOneInterface()); + + verify(builderPort).generateBuilder(commandOutput.capture()); + assertThat(commandOutput.getValue().commands()).contains( + DeleteCommand.builder().name(new TargetName("SutNameBuilder")).scope(CommandScope.CLASS).type(TargetType.INTERFACE) + ); + } + + @Test + void shouldRemoveAllCurrentInterfaces() { + builder.generateBuilder(classWithInterfaces()); + + verify(builderPort).generateBuilder(commandOutput.capture()); + assertThat(commandOutput.getValue().commands()) + .contains(DeleteCommand.builder().name(new TargetName("SutNameBuilder")).scope(CommandScope.CLASS).type(TargetType.INTERFACE)) + .contains(DeleteCommand.builder().name(new TargetName("SutTypeBuilder")).scope(CommandScope.CLASS).type(TargetType.INTERFACE)); + } + + @Test + void shouldCreateLastInterfaceReturnBuiltObject() { + builder.generateBuilder(classWithOneMandatoryParameter()); + + verify(builderPort).generateBuilder(commandOutput.capture()); + assertThat(commandOutput.getValue().commands()).contains( + CreateCommand.builder() + .signature(new CommandSignature("public sealed interface SutFirstNameBuilder permits SutBuilder")) + .content(new CommandContent("Sut firstName(String firstName);")) + .scope(CommandScope.CLASS) + .type(TargetType.INTERFACE) + ); + } + + @Test + void shouldInterfaceImplementNextMandatoryParamInterface() { + builder.generateBuilder(classWithTwoMandatoryParameter()); + + verify(builderPort).generateBuilder(commandOutput.capture()); + assertThat(commandOutput.getValue().commands()) + .contains( + CreateCommand.builder() + .signature(new CommandSignature("public sealed interface SutFirstNameBuilder permits SutBuilder")) + .content(new CommandContent("SutLastNameBuilder firstName(String firstName);")) + .scope(CommandScope.CLASS) + .type(TargetType.INTERFACE) + ) + .contains( + CreateCommand.builder() + .signature(new CommandSignature("public sealed interface SutLastNameBuilder permits SutBuilder")) + .content(new CommandContent("Sut lastName(String lastName);")) + .scope(CommandScope.CLASS) + .type(TargetType.INTERFACE) + ); + } + + @Test + void shouldAddOptionalParamInterfaceAtTheEnd() { + builder.generateBuilder(classWithTwoMandatoryParameterAndOneOptional()); + + verify(builderPort).generateBuilder(commandOutput.capture()); + assertThat(commandOutput.getValue().commands()).contains( + CreateCommand.builder() + .signature(new CommandSignature("public sealed interface SutOptionalBuilder permits SutBuilder")) + .content(new CommandContent("SutOptionalBuilder age(int age);\nSut build();")) + .scope(CommandScope.CLASS) + .type(TargetType.INTERFACE) + ); + } + + @Test + void shouldOptionalParamBeInOptionalBuilder() { + builder.generateBuilder(classWithTwoMandatoryParameterAndTwoOptional()); + + verify(builderPort).generateBuilder(commandOutput.capture()); + assertThat(commandOutput.getValue().commands()) + .contains( + CreateCommand.builder() + .signature(new CommandSignature("public sealed interface SutLastNameBuilder permits SutBuilder")) + .content(new CommandContent("SutOptionalBuilder lastName(String lastName);")) + .scope(CommandScope.CLASS) + .type(TargetType.INTERFACE) + ) + .contains( + CreateCommand.builder() + .signature(new CommandSignature("public sealed interface SutOptionalBuilder permits SutBuilder")) + .content(new CommandContent("SutOptionalBuilder age(int age);\nSutOptionalBuilder gender(String gender);\nSut build();")) + .scope(CommandScope.CLASS) + .type(TargetType.INTERFACE) + ); + } + + @Test + void shouldCreateBuilder() { + builder.generateBuilder(emptyClass()); + + verify(builderPort).generateBuilder(commandOutput.capture()); + assertThat(commandOutput.getValue().commands()).contains( + CreateCommand.builder() + .signature(new CommandSignature("private static final class SutBuilder implements SutFirstNameBuilder")) + .content(new CommandContent(null)) + .scope(CommandScope.CLASS) + .type(TargetType.CLASS) + ); + } + + @Test + void shouldDropAndCreateCreateBuilderIfAlreadyExists() { + builder.generateBuilder(emptyClassWithBuilder()); + + verify(builderPort).generateBuilder(commandOutput.capture()); + assertThat(commandOutput.getValue().commands()).containsSequence( + List.of( + DeleteCommand.builder().name(new TargetName("SutBuilder")).scope(CommandScope.CLASS).type(TargetType.CLASS), + CreateCommand.builder() + .signature(new CommandSignature("private static final class SutBuilder implements SutFirstNameBuilder")) + .content(new CommandContent(null)) + .scope(CommandScope.CLASS) + .type(TargetType.CLASS) + ) + ); + } + + @Test + void shouldCreateBuilderImplementsAllInterfaces() { + builder.generateBuilder(classWithTwoMandatoryParameter()); + + verify(builderPort).generateBuilder(commandOutput.capture()); + assertThat(commandOutput.getValue().commands()).contains( + CreateCommand.builder() + .signature(new CommandSignature("private static final class SutBuilder implements SutFirstNameBuilder, SutLastNameBuilder")) + .content(new CommandContent(null)) + .scope(CommandScope.CLASS) + .type(TargetType.CLASS) + ); + } + + @Test + void shouldCreateBuilderImplementsAllInterfacesWithOptional() { + builder.generateBuilder(classWithTwoMandatoryParameterAndOneOptional()); + + verify(builderPort).generateBuilder(commandOutput.capture()); + assertThat(commandOutput.getValue().commands()).contains( + CreateCommand.builder() + .signature( + new CommandSignature( + "private static final class SutBuilder implements SutFirstNameBuilder, SutLastNameBuilder, SutOptionalBuilder" + ) + ) + .content(new CommandContent(null)) + .scope(CommandScope.CLASS) + .type(TargetType.CLASS) + ); + } + + @Test + void shouldCreateBuilderFieldsWhenNotExists() { + builder.generateBuilder(classWithOneMandatoryParameter()); + + verify(builderPort).generateBuilder(commandOutput.capture()); + assertThat(commandOutput.getValue().commands()).contains( + CreateCommand.builder() + .signature(new CommandSignature("private String firstName;")) + .content(new CommandContent(null)) + .scope(CommandScope.BUILDER) + .type(TargetType.FIELD) + ); + } + + @Test + void shouldNotAlterBuilderFieldWhenExistInCurrentBuilder() { + builder.generateBuilder(classWithBuilderFieldExistingInParams()); + + verify(builderPort).generateBuilder(commandOutput.capture()); + assertThat(commandOutput.getValue().commands()).noneSatisfy(command -> { + assertThat(command) + .isInstanceOfSatisfying(CreateCommand.class, create -> { + assertThat(create.scope()).isEqualTo(CommandScope.BUILDER); + assertThat(create.signature().value()).contains("firstName").contains("lastName"); + }) + .isInstanceOfSatisfying(DeleteCommand.class, delete -> { + assertThat(delete.name()).isEqualTo("firstName").isEqualTo("lastName"); }); - } - - - @Test - void shouldImplementInterfaceInBuilderWhenNotExists() { - builder.generateBuilder(classWithOneMandatoryParameter()); - - verify(builderPort).generateBuilder(commandOutput.capture()); - assertThat(commandOutput.getValue().commands()).contains( - CreateCommand.builder() - .signature(new CommandSignature(""" - @Override - public Sut firstName(String firstName) - """)) - .content(new CommandContent(""" - this.firstName = firstName; - - return new Sut(this);""")) - .scope(CommandScope.BUILDER) - .type(TargetType.METHOD)); - } - - @Test - void shouldImplementMultipleInterfacesInBuilderWhenNotExists() { - builder.generateBuilder(classWithTwoMandatoryParameterAndOneOptional()); - - verify(builderPort).generateBuilder(commandOutput.capture()); - assertThat(commandOutput.getValue().commands()).contains( - CreateCommand.builder() - .signature(new CommandSignature(""" - @Override - public SutLastNameBuilder firstName(String firstName) - """)) - .content(new CommandContent(""" - this.firstName = firstName; - - return this;""")) - .scope(CommandScope.BUILDER) - .type(TargetType.METHOD)) - .contains(CreateCommand.builder() - .signature(new CommandSignature(""" - @Override - public SutOptionalBuilder lastName(String lastName) - """)) - .content(new CommandContent(""" - this.lastName = lastName; - - return this;""")) - .scope(CommandScope.BUILDER) - .type(TargetType.METHOD)) - .contains(CreateCommand.builder() - .signature(new CommandSignature(""" - @Override - public SutOptionalBuilder age(int age) - """)) - .content(new CommandContent(""" - this.age = age; - - return this;""")) - .scope(CommandScope.BUILDER) - .type(TargetType.METHOD)); - } - - @Test - void shouldBuilderImplementBuildMethodIfAtLeastOneFieldOptional() { - builder.generateBuilder(classWithTwoMandatoryParameterAndOneOptional()); - - verify(builderPort).generateBuilder(commandOutput.capture()); - assertThat(commandOutput.getValue().commands()).contains( - CreateCommand.builder() - .signature(new CommandSignature("@Override\npublic Sut build()")) - .content(new CommandContent("return new Sut(this);")) - .scope(CommandScope.BUILDER) - .type(TargetType.METHOD)); - } - - @Test - void shouldCreateClassConstructor() { - builder.generateBuilder(classWithTwoMandatoryParameterAndOneOptional()); - - verify(builderPort).generateBuilder(commandOutput.capture()); - assertThat(commandOutput.getValue().commands()).contains( - CreateCommand.builder() - .signature(new CommandSignature("private Sut(SutBuilder builder)")) - .content(new CommandContent(""" - this.firstName = builder.firstName; - this.lastName = builder.lastName; - this.age = builder.age;""")) - .scope(CommandScope.CLASS) - .type(TargetType.CONSTRUCTOR)); - } - - @Test - void shouldDropClassConstructorWhenExists() { - builder.generateBuilder(classWithConstructor()); - - verify(builderPort).generateBuilder(commandOutput.capture()); - assertThat(commandOutput.getValue().commands()).containsSequence(List.of( - DeleteCommand.builder() - .name(new TargetName("Sut")) - .scope(CommandScope.CLASS) - .type(TargetType.CONSTRUCTOR), - CreateCommand.builder() - .signature(new CommandSignature("private Sut(SutBuilder builder)")) - .content(new CommandContent(""" - this.firstName = builder.firstName;""")) - .scope(CommandScope.CLASS) - .type(TargetType.CONSTRUCTOR))); - } - - @Test - void shouldCreateBuilderMethod() { - builder.generateBuilder(classWithTwoMandatoryParameterAndOneOptional()); - - verify(builderPort).generateBuilder(commandOutput.capture()); - assertThat(commandOutput.getValue().commands()).contains( - CreateCommand.builder() - .signature(new CommandSignature("public static SutFirstNameBuilder builder()")) - .content(new CommandContent("return new SutBuilder();")) - .scope(CommandScope.CLASS) - .type(TargetType.METHOD)); - } - - @Test - void shouldCreateBuilderMethodWithAllOptionalParam() { - builder.generateBuilder(classWithTwoOptionalParameter()); - - verify(builderPort).generateBuilder(commandOutput.capture()); - assertThat(commandOutput.getValue().commands()).contains( - CreateCommand.builder() - .signature(new CommandSignature("public static SutOptionalBuilder builder()")) - .content(new CommandContent("return new SutBuilder();")) - .scope(CommandScope.CLASS) - .type(TargetType.METHOD)); - } - - @Test - void shouldDropBuilderMethodWhenExists() { - builder.generateBuilder(classWithBuilderMethod()); - - verify(builderPort).generateBuilder(commandOutput.capture()); - assertThat(commandOutput.getValue().commands()).containsSequence(List.of( - DeleteCommand.builder() - .name(new TargetName("builder")) - .scope(CommandScope.CLASS) - .type(TargetType.METHOD), - CreateCommand.builder() - .signature(new CommandSignature("public static SutFirstNameBuilder builder()")) - .content(new CommandContent("return new SutBuilder();")) - .scope(CommandScope.CLASS) - .type(TargetType.METHOD))); - } -} \ No newline at end of file + }); + } + + @Test + void shouldImplementInterfaceInBuilderWhenNotExists() { + builder.generateBuilder(classWithOneMandatoryParameter()); + + verify(builderPort).generateBuilder(commandOutput.capture()); + assertThat(commandOutput.getValue().commands()).contains( + CreateCommand.builder() + .signature( + new CommandSignature( + """ + @Override + public Sut firstName(String firstName) + """ + ) + ) + .content( + new CommandContent( + """ + this.firstName = firstName; + + return new Sut(this);""" + ) + ) + .scope(CommandScope.BUILDER) + .type(TargetType.METHOD) + ); + } + + @Test + void shouldImplementMultipleInterfacesInBuilderWhenNotExists() { + builder.generateBuilder(classWithTwoMandatoryParameterAndOneOptional()); + + verify(builderPort).generateBuilder(commandOutput.capture()); + assertThat(commandOutput.getValue().commands()) + .contains( + CreateCommand.builder() + .signature( + new CommandSignature( + """ + @Override + public SutLastNameBuilder firstName(String firstName) + """ + ) + ) + .content( + new CommandContent( + """ + this.firstName = firstName; + + return this;""" + ) + ) + .scope(CommandScope.BUILDER) + .type(TargetType.METHOD) + ) + .contains( + CreateCommand.builder() + .signature( + new CommandSignature( + """ + @Override + public SutOptionalBuilder lastName(String lastName) + """ + ) + ) + .content( + new CommandContent( + """ + this.lastName = lastName; + + return this;""" + ) + ) + .scope(CommandScope.BUILDER) + .type(TargetType.METHOD) + ) + .contains( + CreateCommand.builder() + .signature( + new CommandSignature( + """ + @Override + public SutOptionalBuilder age(int age) + """ + ) + ) + .content( + new CommandContent( + """ + this.age = age; + + return this;""" + ) + ) + .scope(CommandScope.BUILDER) + .type(TargetType.METHOD) + ); + } + + @Test + void shouldBuilderImplementBuildMethodIfAtLeastOneFieldOptional() { + builder.generateBuilder(classWithTwoMandatoryParameterAndOneOptional()); + + verify(builderPort).generateBuilder(commandOutput.capture()); + assertThat(commandOutput.getValue().commands()).contains( + CreateCommand.builder() + .signature(new CommandSignature("@Override\npublic Sut build()")) + .content(new CommandContent("return new Sut(this);")) + .scope(CommandScope.BUILDER) + .type(TargetType.METHOD) + ); + } + + @Test + void shouldCreateClassConstructor() { + builder.generateBuilder(classWithTwoMandatoryParameterAndOneOptional()); + + verify(builderPort).generateBuilder(commandOutput.capture()); + assertThat(commandOutput.getValue().commands()).contains( + CreateCommand.builder() + .signature(new CommandSignature("private Sut(SutBuilder builder)")) + .content( + new CommandContent( + """ + this.firstName = builder.firstName; + this.lastName = builder.lastName; + this.age = builder.age;""" + ) + ) + .scope(CommandScope.CLASS) + .type(TargetType.CONSTRUCTOR) + ); + } + + @Test + void shouldDropClassConstructorWhenExists() { + builder.generateBuilder(classWithConstructor()); + + verify(builderPort).generateBuilder(commandOutput.capture()); + assertThat(commandOutput.getValue().commands()).containsSequence( + List.of( + DeleteCommand.builder().name(new TargetName("Sut")).scope(CommandScope.CLASS).type(TargetType.CONSTRUCTOR), + CreateCommand.builder() + .signature(new CommandSignature("private Sut(SutBuilder builder)")) + .content( + new CommandContent( + """ + this.firstName = builder.firstName;""" + ) + ) + .scope(CommandScope.CLASS) + .type(TargetType.CONSTRUCTOR) + ) + ); + } + + @Test + void shouldCreateBuilderMethod() { + builder.generateBuilder(classWithTwoMandatoryParameterAndOneOptional()); + + verify(builderPort).generateBuilder(commandOutput.capture()); + assertThat(commandOutput.getValue().commands()).contains( + CreateCommand.builder() + .signature(new CommandSignature("public static SutFirstNameBuilder builder()")) + .content(new CommandContent("return new SutBuilder();")) + .scope(CommandScope.CLASS) + .type(TargetType.METHOD) + ); + } + + @Test + void shouldCreateBuilderMethodWithAllOptionalParam() { + builder.generateBuilder(classWithTwoOptionalParameter()); + + verify(builderPort).generateBuilder(commandOutput.capture()); + assertThat(commandOutput.getValue().commands()).contains( + CreateCommand.builder() + .signature(new CommandSignature("public static SutOptionalBuilder builder()")) + .content(new CommandContent("return new SutBuilder();")) + .scope(CommandScope.CLASS) + .type(TargetType.METHOD) + ); + } + + @Test + void shouldDropBuilderMethodWhenExists() { + builder.generateBuilder(classWithBuilderMethod()); + + verify(builderPort).generateBuilder(commandOutput.capture()); + assertThat(commandOutput.getValue().commands()).containsSequence( + List.of( + DeleteCommand.builder().name(new TargetName("builder")).scope(CommandScope.CLASS).type(TargetType.METHOD), + CreateCommand.builder() + .signature(new CommandSignature("public static SutFirstNameBuilder builder()")) + .content(new CommandContent("return new SutBuilder();")) + .scope(CommandScope.CLASS) + .type(TargetType.METHOD) + ) + ); + } +} diff --git a/src/test/io/fabienpuissant/fluent/builder/domain/FluentBuilderFixtures.java b/src/test/io/fabienpuissant/fluent/builder/domain/FluentBuilderFixtures.java index a61179a..b66ede8 100644 --- a/src/test/io/fabienpuissant/fluent/builder/domain/FluentBuilderFixtures.java +++ b/src/test/io/fabienpuissant/fluent/builder/domain/FluentBuilderFixtures.java @@ -4,222 +4,160 @@ public class FluentBuilderFixtures { - private FluentBuilderFixtures() { - } - - public static final String CLASS_NAME = "Sut"; - - static FluentBuilderParameters classWithOneInterface() { - return FluentBuilderParameters.builder() - .context(ExistingClass.builder() - .className(CLASS_NAME) - .isBuilderExist(false) - .interfaces(List.of( - Interface.builder() - .name("SutNameBuilder") - .signatures(List.of("")) - )) - .classMethods(List.of())) - .parameters(new Fields(List.of(Field.builder() - .name("name") - .type("String") - .isOptional(false)))); - } - - static FluentBuilderParameters classWithInterfaces() { - return FluentBuilderParameters.builder() - .context(ExistingClass.builder() - .className(CLASS_NAME) - .isBuilderExist(false) - .interfaces(List.of( - Interface.builder() - .name("SutNameBuilder") - .signatures(List.of("")), - Interface.builder() - .name("SutTypeBuilder") - .signatures(List.of("")) - )) - .classMethods(List.of())) - .parameters(new Fields(List.of(Field.builder() - .name("name") - .type("String") - .isOptional(false), - Field.builder() - .name("type") - .type("String") - .isOptional(false) - ))); - } - - static FluentBuilderParameters classWithOneMandatoryParameter() { - return FluentBuilderParameters.builder() - .context(ExistingClass.builder() - .className(CLASS_NAME) - .isBuilderExist(false) - .interfaces(List.of()) - .classMethods(List.of())) - .parameters(new Fields(List.of(Field.builder() - .name("firstName") - .type("String") - .isOptional(false)))); - } - - static FluentBuilderParameters classWithTwoMandatoryParameter() { - return FluentBuilderParameters.builder() - .context(ExistingClass.builder() - .className(CLASS_NAME) - .isBuilderExist(false) - .interfaces(List.of()) - .classMethods(List.of())) - .parameters(new Fields(List.of(Field.builder() - .name("firstName") - .type("String") - .isOptional(false), - Field.builder() - .name("lastName") - .type("String") - .isOptional(false)))); - } - - static FluentBuilderParameters classWithTwoMandatoryParameterAndOneOptional() { - return FluentBuilderParameters.builder() - .context(ExistingClass.builder() - .className(CLASS_NAME) - .isBuilderExist(false) - .interfaces(List.of()) - .classMethods(List.of())) - .parameters(new Fields(List.of(Field.builder() - .name("firstName") - .type("String") - .isOptional(false), - Field.builder() - .name("lastName") - .type("String") - .isOptional(false), - Field.builder() - .name("age") - .type("int") - .isOptional(true)))); - } - - static FluentBuilderParameters classWithTwoMandatoryParameterAndTwoOptional() { - return FluentBuilderParameters.builder() - .context(ExistingClass.builder() - .className(CLASS_NAME) - .isBuilderExist(false) - .interfaces(List.of()) - .classMethods(List.of())) - .parameters(new Fields(List.of(Field.builder() - .name("firstName") - .type("String") - .isOptional(false), - Field.builder() - .name("lastName") - .type("String") - .isOptional(false), - Field.builder() - .name("age") - .type("int") - .isOptional(true), - Field.builder() - .name("gender") - .type("String") - .isOptional(true)))); - } - - static FluentBuilderParameters emptyClass() { - return FluentBuilderParameters.builder() - .context(ExistingClass.builder() - .className(CLASS_NAME) - .isBuilderExist(false) - .interfaces(List.of()) - .classMethods(List.of())) - .parameters(new Fields(List.of(Field.builder() - .name("firstName") - .type("String") - .isOptional(false)))); - } - - static FluentBuilderParameters emptyClassWithBuilder() { - return FluentBuilderParameters.builder() - .context(ExistingClass.builder() - .className(CLASS_NAME) - .isBuilderExist(true) - .interfaces(List.of()) - .classMethods(List.of())) - .parameters(new Fields(List.of(Field.builder() - .name("firstName") - .type("String") - .isOptional(false)))); - } - - static FluentBuilderParameters classWithBuilderFieldExistingInParams() { - return FluentBuilderParameters.builder() - .context(ExistingClass.builder() - .className(CLASS_NAME) - .isBuilderExist(true) - .interfaces(List.of()) - .classMethods(List.of())) - .parameters(new Fields(List.of(Field.builder() - .name("firstName") - .type("String") - .isOptional(false), - Field.builder() - .name("lastName") - .type("String") - .isOptional(false)))); - } - - - static FluentBuilderParameters classWithBuilderMethod() { - return FluentBuilderParameters.builder() - .context(ExistingClass.builder() - .className(CLASS_NAME) - .isBuilderExist(true) - - .interfaces(List.of()) - .classMethods(List.of(Method.builder() - .signature("public static SutFirstNameBuilder builder()") - .content("return new SutBuilder();")))) - .parameters(new Fields(List.of(Field.builder() - .name("firstName") - .type("Strind") - .isOptional(false)))); - } - - static FluentBuilderParameters classWithConstructor() { - return FluentBuilderParameters.builder() - .context(ExistingClass.builder() - .className(CLASS_NAME) - .isBuilderExist(true) - .interfaces(List.of()) - .classMethods(List.of(Method.builder() - .signature("public static SutFirstNameBuilder builder()") - .content("return new SutBuilder();"), - Method.builder() - .signature("private Sut(Sut.SutBuilder builder)") - .content("this.firstName = builder.firstName;")))) - .parameters(new Fields(List.of(Field.builder() - .name("firstName") - .type("Strind") - .isOptional(false)))); - } - - static FluentBuilderParameters classWithTwoOptionalParameter() { - return FluentBuilderParameters.builder() - .context(ExistingClass.builder() - .className(CLASS_NAME) - .isBuilderExist(false) - .interfaces(List.of()) - .classMethods(List.of())) - .parameters(new Fields(List.of(Field.builder() - .name("firstName") - .type("String") - .isOptional(true), - Field.builder() - .name("lastName") - .type("String") - .isOptional(true)))); - } - + private FluentBuilderFixtures() {} + + public static final String CLASS_NAME = "Sut"; + + static FluentBuilderParameters classWithOneInterface() { + return FluentBuilderParameters.builder() + .context( + ExistingClass.builder() + .className(CLASS_NAME) + .isBuilderExist(false) + .interfaces(List.of(Interface.builder().name("SutNameBuilder").signatures(List.of("")))) + .classMethods(List.of()) + ) + .parameters(new Fields(List.of(Field.builder().name("name").type("String").isOptional(false)))); + } + + static FluentBuilderParameters classWithInterfaces() { + return FluentBuilderParameters.builder() + .context( + ExistingClass.builder() + .className(CLASS_NAME) + .isBuilderExist(false) + .interfaces( + List.of( + Interface.builder().name("SutNameBuilder").signatures(List.of("")), + Interface.builder().name("SutTypeBuilder").signatures(List.of("")) + ) + ) + .classMethods(List.of()) + ) + .parameters( + new Fields( + List.of( + Field.builder().name("name").type("String").isOptional(false), + Field.builder().name("type").type("String").isOptional(false) + ) + ) + ); + } + + static FluentBuilderParameters classWithOneMandatoryParameter() { + return FluentBuilderParameters.builder() + .context(ExistingClass.builder().className(CLASS_NAME).isBuilderExist(false).interfaces(List.of()).classMethods(List.of())) + .parameters(new Fields(List.of(Field.builder().name("firstName").type("String").isOptional(false)))); + } + + static FluentBuilderParameters classWithTwoMandatoryParameter() { + return FluentBuilderParameters.builder() + .context(ExistingClass.builder().className(CLASS_NAME).isBuilderExist(false).interfaces(List.of()).classMethods(List.of())) + .parameters( + new Fields( + List.of( + Field.builder().name("firstName").type("String").isOptional(false), + Field.builder().name("lastName").type("String").isOptional(false) + ) + ) + ); + } + + static FluentBuilderParameters classWithTwoMandatoryParameterAndOneOptional() { + return FluentBuilderParameters.builder() + .context(ExistingClass.builder().className(CLASS_NAME).isBuilderExist(false).interfaces(List.of()).classMethods(List.of())) + .parameters( + new Fields( + List.of( + Field.builder().name("firstName").type("String").isOptional(false), + Field.builder().name("lastName").type("String").isOptional(false), + Field.builder().name("age").type("int").isOptional(true) + ) + ) + ); + } + + static FluentBuilderParameters classWithTwoMandatoryParameterAndTwoOptional() { + return FluentBuilderParameters.builder() + .context(ExistingClass.builder().className(CLASS_NAME).isBuilderExist(false).interfaces(List.of()).classMethods(List.of())) + .parameters( + new Fields( + List.of( + Field.builder().name("firstName").type("String").isOptional(false), + Field.builder().name("lastName").type("String").isOptional(false), + Field.builder().name("age").type("int").isOptional(true), + Field.builder().name("gender").type("String").isOptional(true) + ) + ) + ); + } + + static FluentBuilderParameters emptyClass() { + return FluentBuilderParameters.builder() + .context(ExistingClass.builder().className(CLASS_NAME).isBuilderExist(false).interfaces(List.of()).classMethods(List.of())) + .parameters(new Fields(List.of(Field.builder().name("firstName").type("String").isOptional(false)))); + } + + static FluentBuilderParameters emptyClassWithBuilder() { + return FluentBuilderParameters.builder() + .context(ExistingClass.builder().className(CLASS_NAME).isBuilderExist(true).interfaces(List.of()).classMethods(List.of())) + .parameters(new Fields(List.of(Field.builder().name("firstName").type("String").isOptional(false)))); + } + + static FluentBuilderParameters classWithBuilderFieldExistingInParams() { + return FluentBuilderParameters.builder() + .context(ExistingClass.builder().className(CLASS_NAME).isBuilderExist(true).interfaces(List.of()).classMethods(List.of())) + .parameters( + new Fields( + List.of( + Field.builder().name("firstName").type("String").isOptional(false), + Field.builder().name("lastName").type("String").isOptional(false) + ) + ) + ); + } + + static FluentBuilderParameters classWithBuilderMethod() { + return FluentBuilderParameters.builder() + .context( + ExistingClass.builder() + .className(CLASS_NAME) + .isBuilderExist(true) + .interfaces(List.of()) + .classMethods( + List.of(Method.builder().signature("public static SutFirstNameBuilder builder()").content("return new SutBuilder();")) + ) + ) + .parameters(new Fields(List.of(Field.builder().name("firstName").type("Strind").isOptional(false)))); + } + + static FluentBuilderParameters classWithConstructor() { + return FluentBuilderParameters.builder() + .context( + ExistingClass.builder() + .className(CLASS_NAME) + .isBuilderExist(true) + .interfaces(List.of()) + .classMethods( + List.of( + Method.builder().signature("public static SutFirstNameBuilder builder()").content("return new SutBuilder();"), + Method.builder().signature("private Sut(Sut.SutBuilder builder)").content("this.firstName = builder.firstName;") + ) + ) + ) + .parameters(new Fields(List.of(Field.builder().name("firstName").type("Strind").isOptional(false)))); + } + + static FluentBuilderParameters classWithTwoOptionalParameter() { + return FluentBuilderParameters.builder() + .context(ExistingClass.builder().className(CLASS_NAME).isBuilderExist(false).interfaces(List.of()).classMethods(List.of())) + .parameters( + new Fields( + List.of( + Field.builder().name("firstName").type("String").isOptional(true), + Field.builder().name("lastName").type("String").isOptional(true) + ) + ) + ); + } }