{"id":51105387,"url":"https://github.com/lemon-ant/JHarmonizer","last_synced_at":"2026-07-09T19:00:51.808Z","repository":{"id":356160452,"uuid":"1018474240","full_name":"lemon-ant/JHarmonizer","owner":"lemon-ant","description":"Make Java source layout deterministic: reorder class members safely, keep accessors together, format java-source, and enforce style in CI.","archived":false,"fork":false,"pushed_at":"2026-06-02T09:05:41.000Z","size":4404,"stargazers_count":16,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-02T10:28:34.067Z","etag":null,"topics":["ci-cd-automation","code-formatter","code-quality","developer-tools","development-tools","formatter","java","java-code-audit","java-code-formatter","java-code-quality","java-development","java-development-tools","java-formatter","java-static-analysis","maven-plugin","static-analysis"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lemon-ant.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":null,"code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"github":["AntonLem"],"buy_me_a_coffee":"antonlem"}},"created_at":"2025-07-12T10:40:46.000Z","updated_at":"2026-06-02T09:14:47.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/lemon-ant/JHarmonizer","commit_stats":null,"previous_names":["lemon-ant/jharmonizer"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/lemon-ant/JHarmonizer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lemon-ant%2FJHarmonizer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lemon-ant%2FJHarmonizer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lemon-ant%2FJHarmonizer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lemon-ant%2FJHarmonizer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lemon-ant","download_url":"https://codeload.github.com/lemon-ant/JHarmonizer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lemon-ant%2FJHarmonizer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35309828,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-09T02:00:07.329Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ci-cd-automation","code-formatter","code-quality","developer-tools","development-tools","formatter","java","java-code-audit","java-code-formatter","java-code-quality","java-development","java-development-tools","java-formatter","java-static-analysis","maven-plugin","static-analysis"],"created_at":"2026-06-24T14:00:22.743Z","updated_at":"2026-07-09T19:00:51.801Z","avatar_url":"https://github.com/lemon-ant.png","language":"Java","funding_links":["https://github.com/sponsors/AntonLem","https://buymeacoffee.com/antonlem"],"categories":["Projects"],"sub_categories":["Code Formatting"],"readme":"\u003c!--\nSPDX-FileCopyrightText: 2026 Anton Lem \u003cantonlem78@gmail.com\u003e\nSPDX-License-Identifier: Apache-2.0\n--\u003e\n\n# JHarmonizer\n\n[![Verify](https://github.com/lemon-ant/JHarmonizer/actions/workflows/verify.yml/badge.svg)](https://github.com/lemon-ant/JHarmonizer/actions/workflows/verify.yml)\n[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)\n[![Java](https://img.shields.io/badge/java-17%2B-orange.svg)](https://adoptium.net/)\n[![Coverage](https://img.shields.io/codecov/c/github/lemon-ant/JHarmonizer)](https://codecov.io/gh/lemon-ant/JHarmonizer)\n\nJHarmonizer **sorts and formats Java source files** while keeping the code safe.\nIt reorders class members — fields, constructors, methods, nested types, initializer blocks — according to\nconfigurable rules, and formats the output with [Palantir Java Format](https://github.com/palantir/palantir-java-format).\n\nWhat sets it apart from a plain formatter: formatters only adjust whitespace and style — they do not\nreorder members. JHarmonizer does reorder them, and before moving anything it checks which fields and\nblocks depend on each other's position so that the result **compiles and runs correctly** — not just\nlooks different.\n\n**Why not just use IntelliJ or Checkstyle?**\nIDEs cannot run in CI, and checkers only flag without fixing.\nIDE arrangement rules also apply a single global layout to every class — there is no way to define\ndifferent ordering rules for test classes, DTOs, annotated controllers, or other class-type selectors.\nJHarmonizer's selector DSL provides that flexibility out of the box.\nSee [docs/motivation.md](docs/motivation.md) for the full comparison.\n\n## Quick Start\n\nThe primary usage pattern is to integrate JHarmonizer into the Maven build so sources are automatically\nreordered and/or checked without manual invocation.\n\n### Auto-reorder on every build\n\nBind the `reorder` goal to the `process-sources` phase so sources are reordered before compilation.\n`process-sources` is the standard Maven phase for reformatting existing sources (used by tools such as\nSpotless); it runs after `generate-sources` and before `compile`.\n\n```xml\n\u003cbuild\u003e\n    \u003cplugins\u003e\n        \u003cplugin\u003e\n            \u003cgroupId\u003eio.github.lemon-ant.jharmonizer\u003c/groupId\u003e\n            \u003cartifactId\u003ejharmonizer-maven-plugin\u003c/artifactId\u003e\n            \u003cversion\u003e1.0.1\u003c/version\u003e\n            \u003cexecutions\u003e\n                \u003cexecution\u003e\n                    \u003cphase\u003eprocess-sources\u003c/phase\u003e\n                    \u003cgoals\u003e\n                        \u003cgoal\u003ereorder\u003c/goal\u003e\n                    \u003c/goals\u003e\n                \u003c/execution\u003e\n            \u003c/executions\u003e\n        \u003c/plugin\u003e\n    \u003c/plugins\u003e\n\u003c/build\u003e\n```\n\n### Enforce order in CI\n\n`check-fast` and `check-all` default to the `validate` phase — the build fails early,\nbefore any compilation happens:\n\n```xml\n\u003cbuild\u003e\n    \u003cplugins\u003e\n        \u003cplugin\u003e\n            \u003cgroupId\u003eio.github.lemon-ant.jharmonizer\u003c/groupId\u003e\n            \u003cartifactId\u003ejharmonizer-maven-plugin\u003c/artifactId\u003e\n            \u003cversion\u003e1.0.1\u003c/version\u003e\n            \u003cexecutions\u003e\n                \u003cexecution\u003e\n                    \u003cgoals\u003e\n                        \u003cgoal\u003echeck-fast\u003c/goal\u003e\n                    \u003c/goals\u003e\n                \u003c/execution\u003e\n            \u003c/executions\u003e\n        \u003c/plugin\u003e\n    \u003c/plugins\u003e\n\u003c/build\u003e\n```\n\n`check-fast` immediately halts the build pipeline the moment it detects an out-of-order or unformatted file —\nno further processing happens. `check-all` scans all files, collects every violation, and only then interrupts the\nbuild with the full report; set `-Djharmonizer.failOnViolation=false` to make `check-all` report violations without\nfailing the build.\n\n### Manual invocation\n\n```bash\nmvn jharmonizer:reorder      # reorder all sources\nmvn jharmonizer:check-all        # report all violations\nmvn jharmonizer:check-fast   # fail fast on first violation\n```\n\n### Reconfigure with the YAML DSL\n\nFor Maven projects, create `jharmonizer.yml` in the project root next to `pom.xml` and put only the\nrules you want to override there. The Maven plugin loads that file automatically and merges it over the\nembedded defaults; if the file is absent, the defaults are used as-is.\n\n```yaml\n# jharmonizer.yml\nbackups-enabled: false\nprocessing-statistics-mode: DISABLED\n\ntype-members-ordering:\n  - name: Spring Controllers\n    includes:\n      - '@Controller'\n      - '@RestController'\n    ordering-rules: [ visibility-desc, alpha ]\n```\n\nUse `\u003cconfigFile\u003e` or `-Djharmonizer.configFile=...` if your project keeps the overlay under another name,\nfor example `JHarmonizer.yaml`. See the [quick reconfiguration guide](docs/reconfiguration.md) for how\nMaven and CLI overlays are loaded and merged, and the [configuration DSL reference](docs/config-dsl.md) for\nall selector tokens, ordering rules, and YAML fields.\n\n### CLI\n\nJHarmonizer is also available as a standalone CLI fat JAR for use outside of Maven.\n\n**Download directly** (no build required):\n[jharmonizer-cli-1.0.1.jar](https://repo1.maven.org/maven2/io/github/lemon-ant/jharmonizer/jharmonizer-cli/1.0.1/jharmonizer-cli-1.0.1.jar)\n\nBrowse all versions on [Maven Central](https://central.sonatype.com/artifact/io.github.lemon-ant.jharmonizer/jharmonizer-cli).\n\n```bash\njava -jar jharmonizer-cli-1.0.1.jar reorder --base-dir src/main/java\n```\n\nSee [`cli/README.md`](cli/README.md) for full command-line usage, all options, exit codes, and CI integration examples.\n\n### Opt-out directives\n\nJHarmonizer supports two opt-out directives placed as source comments.\n\n```java\n// @jharmonizer:fully-off   // disable all harmonization for this file or type\n// @jharmonizer:sort-off    // disable sorting only; formatting still runs\n```\n\nDirective matching is case-insensitive. Both line (`//`) and block (`/* */`) comment forms are supported.\nDirectives can be placed at **file scope** (in the compilation-unit preamble) or **type scope** (immediately\nbefore a type declaration).\n\nFor the full reference — placement rules, scope semantics, and unsupported tokens — see [`docs/directives.md`](docs/directives.md).\n\n## ⭐ Ways to support this project\n\nI'm an open-source developer building reliable, intelligent tooling for the Java community 🛠️.\n\nThe ideas behind JHarmonizer are simple, but implementing them correctly turned out to be surprisingly hard ⚙️.\nThere is a large backlog of planned features — smarter ordering rules, IDE plugins, more formatting options, and\ndeeper static analysis integration — but delivering them takes a huge amount of time and effort ⏳.\n\n**This project is free for you, but it is not free for me 💙.** Every hour spent here is a personal investment —\nand beyond time, I also put real money into it: AI tooling, compute credits, and the infra that powers\ndevelopment 💸. All of that goes toward making this tool better for you.\n\nYour support is the most direct feedback I can receive 💬 — it tells me the project matters and gives me the energy to\nkeep pushing forward 🚀. And every contribution comes back to you as a smarter, more capable tool that saves you even\nmore time with each new release.\n\nIf this project is useful to you, please consider:\n\n- ⭐ **Star the repository** — it improves visibility and takes 2 seconds.\n- ☕ **[Buy me a coffee](https://buymeacoffee.com/antonlem)** — even a small one-time contribution makes a real\n  difference and keeps me motivated.\n- 💖 **[GitHub Sponsors](https://github.com/sponsors/AntonLem)** — recurring sponsorship directly through GitHub\n  to support ongoing development of new features.\n\nEvery donation, no matter how small, directly accelerates the roadmap 🙏. Thank you!\n\n## Current status\n\n- Core pipeline is available: parse → group → sort → serialize → format.\n- A declaration-order dependency graph is built to avoid reorderings that would break compilation\n  or field/constant initialization. The current model handles direct initializer references\n  (forward and backward, including explicit `this.` / `\u003cEnclosingType\u003e.` qualifiers), enum\n  constant initializers, instance and static initializer blocks, blank-final definite-assignment\n  ordering, cross-type constant back-references, and accessor bundling.\n- Comment-based opt-out directives are supported for file scope and type scope.\n\n## Roadmap (next versions)\n\nThe five most impactful planned features for everyday Java development:\n\n- **Enum constant ordering strategies** — configurable `PRESERVE` / `ALPHA_ASC` / `ALPHA_DESC` ordering for enum constants, with placement guarantees that keep them before other enum members.\n- **Annotation ordering policies** — configurable `ALPHA` / `LENGTH_ASC` / `LENGTH_DESC` ordering for annotations on declarations, keeping annotation lists deterministic and reducing diff noise.\n- **Record member ordering** — dedicated ordering strategies for record components, with safety guarantees that preserve generated member contracts and binary compatibility.\n- **Vendor-format configuration adapters** — import existing IntelliJ IDEA or Eclipse formatter/arrangement profiles directly so teams do not have to duplicate their configuration in a separate `jharmonizer.yml`.\n- **Git-aware changed-files processing** — limit sorting and checking to files that actually changed in Git (working tree vs. index, branch vs. merge-base), so large repositories stay fast in CI and pre-commit hooks.\n\nThe full idea backlog is significantly longer — see [docs/TODO.md](docs/TODO.md) for the complete list, ordered from the most developer-visible features to the most internal improvements.\n\n## Known limitations\n\n- **Non-idempotent formatter output:** Palantir formatter can produce slightly different results across\n  consecutive runs for some long or heavily wrapped constructs. This is an upstream issue unrelated to JHarmonizer.\n- **Maven archetype template files:** files containing `${package}` or similar placeholders are not valid\n  Java source and are skipped with a warning.\n\nSee [`docs/known-limitations.md`](docs/known-limitations.md) for details and workarounds.\n\n## Build\n\n```bash\nmvn clean verify\n```\n\n## 📖 Documentation\n\n- [Javadoc (latest)](https://javadoc.io/doc/io.github.lemon-ant/jharmonizer-core)\n\n## Contributing\n\nContributions are welcome! Please read [CONTRIBUTING.md](.github/CONTRIBUTING.md) to get started.\nSee [CHANGELOG.md](CHANGELOG.md) for what is planned.\n\n## License\n\nCopyright 2026 Anton Lem\n\nLicensed under the [Apache License, Version 2.0](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flemon-ant%2FJHarmonizer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flemon-ant%2FJHarmonizer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flemon-ant%2FJHarmonizer/lists"}