RepoPilotOpen in app →

square/javapoet

A Java API for generating .java source files.

Healthy

Healthy across all four use cases

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • 10 active contributors
  • Distributed ownership (top contributor 49% of recent commits)
  • Apache-2.0 licensed
Show all 6 evidence items →
  • CI configured
  • Tests present
  • Stale — last commit 2y ago

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/square/javapoet)](https://repopilot.app/r/square/javapoet)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/square/javapoet on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: square/javapoet

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/square/javapoet shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across all four use cases

  • 10 active contributors
  • Distributed ownership (top contributor 49% of recent commits)
  • Apache-2.0 licensed
  • CI configured
  • Tests present
  • ⚠ Stale — last commit 2y ago

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live square/javapoet repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/square/javapoet.

What it runs against: a local clone of square/javapoet — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in square/javapoet | Confirms the artifact applies here, not a fork | | 2 | License is still Apache-2.0 | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 604 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>square/javapoet</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of square/javapoet. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/square/javapoet.git
#   cd javapoet
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of square/javapoet and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "square/javapoet(\\.git)?\\b" \\
  && ok "origin remote is square/javapoet" \\
  || miss "origin remote is not square/javapoet (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
  && ok "license is Apache-2.0" \\
  || miss "license drift — was Apache-2.0 at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "src/main/java/com/squareup/javapoet/JavaFile.java" \\
  && ok "src/main/java/com/squareup/javapoet/JavaFile.java" \\
  || miss "missing critical file: src/main/java/com/squareup/javapoet/JavaFile.java"
test -f "src/main/java/com/squareup/javapoet/TypeSpec.java" \\
  && ok "src/main/java/com/squareup/javapoet/TypeSpec.java" \\
  || miss "missing critical file: src/main/java/com/squareup/javapoet/TypeSpec.java"
test -f "src/main/java/com/squareup/javapoet/CodeBlock.java" \\
  && ok "src/main/java/com/squareup/javapoet/CodeBlock.java" \\
  || miss "missing critical file: src/main/java/com/squareup/javapoet/CodeBlock.java"
test -f "src/main/java/com/squareup/javapoet/TypeName.java" \\
  && ok "src/main/java/com/squareup/javapoet/TypeName.java" \\
  || miss "missing critical file: src/main/java/com/squareup/javapoet/TypeName.java"
test -f "src/main/java/com/squareup/javapoet/CodeWriter.java" \\
  && ok "src/main/java/com/squareup/javapoet/CodeWriter.java" \\
  || miss "missing critical file: src/main/java/com/squareup/javapoet/CodeWriter.java"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 604 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~574d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/square/javapoet"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

JavaPoet is a Java API for programmatically generating .java source files at runtime. It provides a fluent builder interface to construct classes, methods, fields, annotations, and type declarations as immutable objects, then serialize them to valid Java source code. Commonly used for annotation processors, code generators, and metadata-driven code generation (e.g., database schema → DAOs). Single-package monolith: core API lives in src/main/java/com/squareup/javapoet/ with ~16 specification classes (TypeSpec.java, MethodSpec.java, FieldSpec.java, AnnotationSpec.java, etc.) that build immutable models. CodeWriter.java handles serialization; NameAllocator.java avoids name collisions. Tests mirror the structure under src/test/java/com/squareup/javapoet/.

👥Who it's for

Library maintainers and framework developers who build annotation processors (like Dagger, Butterknife, Room), code generators for build tools, or metadata-to-code transformers. They need to emit syntactically correct Java source without string concatenation or AST complexity.

🌱Maturity & risk

Mature but deprecated as of 2020-10-10. The project has ~441KB of Java code across 17 core specification classes with comprehensive test coverage (25+ test files using JUnit 4 + Google Truth) and active CI via GitHub Actions. However, it is no longer maintained by Square; the README explicitly directs users to Palantir's fork for latest Java language features.

Low risk for stable use but high risk for new projects: Square discontinued maintenance over 3 years ago, so no support for Java 17+ features (records, sealed classes, pattern matching). The dependency tree is minimal (only test deps: JUnit 4.13.2, Truth 1.4.4, compile-testing 0.21.0), but Java language evolution will outpace this version. Consider Palantir's fork for active development.

Active areas of work

Project is in maintenance mode. No active development visible—it's deprecated and community is migrated to Palantir's fork. The pom.xml shows version 1.14.0-SNAPSHOT, suggesting the last release cycle may have stalled.

🚀Get running

git clone https://github.com/square/javapoet.git
cd javapoet
mvn clean install
mvn test

Daily commands: No server/runtime. Build project with mvn clean install to generate JAR at target/javapoet-1.14.0-SNAPSHOT.jar. Use in your own code by adding to your project's classpath and calling builder APIs (see README example).

🗺️Map of the codebase

  • src/main/java/com/squareup/javapoet/JavaFile.java — Entry point for generating complete .java source files; orchestrates package, imports, and type declarations.
  • src/main/java/com/squareup/javapoet/TypeSpec.java — Core abstraction for class, interface, enum, and annotation type generation; every class-like construct flows through here.
  • src/main/java/com/squareup/javapoet/CodeBlock.java — Manages code fragment generation with format placeholders and parameter substitution; powers all method bodies and field initializers.
  • src/main/java/com/squareup/javapoet/TypeName.java — Abstract base for all Java type representations; critical for type hierarchy, generics, and import resolution.
  • src/main/java/com/squareup/javapoet/CodeWriter.java — Handles low-level emission of code to output streams with indentation, import management, and line wrapping.
  • src/main/java/com/squareup/javapoet/MethodSpec.java — Declarative builder for methods with parameters, annotations, and code blocks; fundamental to functional code generation.
  • src/main/java/com/squareup/javapoet/ClassName.java — Represents qualified class names with package context; essential for type resolution and import deduplication.

🛠️How to make changes

Generate a new class with fields and methods

  1. Create a TypeSpec using TypeSpec.classBuilder() with class name (src/main/java/com/squareup/javapoet/TypeSpec.java)
  2. Add fields using FieldSpec.builder() with type and name (src/main/java/com/squareup/javapoet/FieldSpec.java)
  3. Add methods using MethodSpec.methodBuilder() with code blocks (src/main/java/com/squareup/javapoet/MethodSpec.java)
  4. Wrap TypeSpec in JavaFile with package and write to stream (src/main/java/com/squareup/javapoet/JavaFile.java)

Generate code with generic types and complex signatures

  1. Use ClassName.get() to reference types with packages (src/main/java/com/squareup/javapoet/ClassName.java)
  2. Build parameterized types with ParameterizedTypeName.get() (src/main/java/com/squareup/javapoet/ParameterizedTypeName.java)
  3. Add type variables with TypeVariableName.get() for generic bounds (src/main/java/com/squareup/javapoet/TypeVariableName.java)
  4. Use in MethodSpec parameters and return types (src/main/java/com/squareup/javapoet/ParameterSpec.java)

Generate annotated code with custom annotations

  1. Create AnnotationSpec using AnnotationSpec.builder() (src/main/java/com/squareup/javapoet/AnnotationSpec.java)
  2. Add annotation members via addMember() with format strings (src/main/java/com/squareup/javapoet/AnnotationSpec.java)
  3. Apply annotations to TypeSpec, MethodSpec, FieldSpec, or ParameterSpec via addAnnotation() (src/main/java/com/squareup/javapoet/TypeSpec.java)

Generate method implementations with formatted code blocks

  1. Build CodeBlock with format string placeholders and arguments (src/main/java/com/squareup/javapoet/CodeBlock.java)
  2. Use $S for strings, $L for literals, $T for types, $N for names (src/main/java/com/squareup/javapoet/CodeBlock.java)
  3. Assign CodeBlock to MethodSpec.addCode() (src/main/java/com/squareup/javapoet/MethodSpec.java)
  4. Let CodeWriter handle imports and formatting on write() (src/main/java/com/squareup/javapoet/CodeWriter.java)

🔧Why these technologies

  • Builder pattern — Provides fluent, readable API for composing complex Java structures with optional and required fields; core to usability.
  • Format strings ($T, $L, $S, $N) — Allows safe code generation with type-safe placeholder substitution, automatically managing imports and escaping.
  • AST-like object graph — Represents Java structures as declarative objects (TypeSpec, MethodSpec, etc.) before emission, enabling validation and reuse.
  • CodeWriter with two-pass emission — First collects all types referenced in code blocks, then emits imports once; avoids import duplication and forward-reference issues.

⚖️Trade-offs already made

  • No reflection-based type inspection by default; users provide ClassName/TypeName explicitly

    • Why: Avoids runtime classpath dependencies and allows generation for types not present at build time.
    • Consequence: Users must manually specify types; reduces magic but increases verbosity for complex type hierarchies.
  • Single-file generation only; no cross-file dependency resolution

    • Why: Keeps scope simple and library lightweight; each file is generated independently.
    • Consequence: Users must orchestrate multi-file generation externally; no built-in support for circular dependencies or cross-file imports.
  • Format-string-based code injection ($T, $L, etc.) rather than AST node types

    • Why: Minimal API surface; simpler than full expression/statement AST modeling.
    • Consequence: Limited compile-time safety for generated code logic; users can generate syntactically invalid code.
  • Deprecated since Oct 2020; recommend Palantir's javapoet fork for new projects

    • Why: Square deprioritized maintenance; Palantir fork tracks newer Java language features.
    • Consequence: Project will not add Java 9+ features (modules, records, sealed classes, etc.); users should migrate if targeting modern Java.

🚫Non-goals (don't propose these)

  • Does not parse existing .java source files; generation-only, not round-trip capable.
  • Does not

🪤Traps & gotchas

No required env vars or external services. Java 8+ required (pom.xml: <java.version>1.8</java.version>). No support for Java 17+ features (records, sealed classes, pattern matching) due to project deprecation. CodeBlock format strings are un-validated at build time—syntax errors appear only when code is written, not when building specs. NameAllocator is per-instance (stateful), so reusing a single allocator across multiple independent name-generation contexts will cause collisions.

🏗️Architecture

💡Concepts to learn

  • Builder Pattern — Every spec class (MethodSpec, TypeSpec, FieldSpec, etc.) uses fluent builders to construct immutable objects—essential for JavaPoet's API ergonomics and why you never directly instantiate specs
  • Code Generation via Format Strings — JavaPoet uses placeholder format strings ($T for type, $S for string literal, $N for name) instead of AST walking—keeps the library lightweight and composable but requires understanding the placeholder protocol
  • Name Collision Avoidance (NameAllocator) — Generated code must avoid shadowing reserved identifiers and user-provided names—NameAllocator de-duplicates and munges names so generated parameter/field names never conflict with visible scope
  • Type Import Management (Type.toString vs raw type names) — JavaPoet tracks whether types need imports and emits qualified names or short names accordingly—critical for avoiding import statement explosion and handling name shadowing across packages
  • Annotation Processing API Integration — JavaPoet is designed to integrate with javax.annotation.processing—feeds Elements/TypeMirrors from the APT environment into ClassName/TypeName to emit code that matches runtime types
  • Immutability + Defensive Copying — All specs are immutable; builder methods return new instances—enables safe concurrent use and predictable code generation without mutation surprises
  • Line Wrapping Strategy (80-char soft limit) — JavaPoet uses LineWrapper to break long lines intelligently (e.g., method signatures, chained calls) to stay under column limits—important for readability of generated code and diff compatibility
  • palantir/javapoet — Active fork of Square's JavaPoet—adds support for Java 11+ features (var, text blocks, records, sealed classes) where Square's version stalled at Java 8
  • google/auto — Companion framework (AutoValue, AutoFactory, AutoService) that uses JavaPoet-like code generation for reducing boilerplate in value types and annotation processing
  • square/kotlinpoet — Sister project applying the same builder + CodeBlock pattern to Kotlin source generation; shares architectural philosophy with JavaPoet
  • google/dagger — Major consumer of JavaPoet—uses it in annotation processors to generate dependency injection component classes at compile-time
  • jakewharton/butterknife — Historical major consumer of JavaPoet—generated view-binding boilerplate via annotation processors (now deprecated in favor of synthetic bindings)

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive test coverage for LineWrapper edge cases

LineWrapper.java handles critical line-wrapping logic for code generation, but LineWrapperTest.java appears to have minimal coverage. This is high-value because incorrect line wrapping can produce malformed Java files. New contributor can add tests for: wrapping with nested generics, wrapping with long annotations, wrapping with lambda expressions, and edge cases around the 100-character default limit.

  • [ ] Review src/main/java/com/squareup/javapoet/LineWrapper.java for all public methods
  • [ ] Examine existing src/test/java/com/squareup/javapoet/LineWrapperTest.java to identify gaps
  • [ ] Add tests for generic type wrapping (e.g., Map<String, List<MyLongClassName>>)
  • [ ] Add tests for annotation wrapping with multiple parameters
  • [ ] Add tests for method chaining and nested code blocks
  • [ ] Verify tests pass with mvn clean test

Add tests for CodeWriter interaction with complex ParameterSpec scenarios

CodeWriter.java is the core emission engine, but CodeWriterTest.java may not cover all parameter specification edge cases like varargs, annotations on parameters, and type variable parameters. This is valuable because parameter emission is fundamental to method generation correctness.

  • [ ] Review src/main/java/com/squareup/javapoet/CodeWriter.java and emitParameter methods
  • [ ] Check src/main/java/com/squareup/javapoet/ParameterSpec.java for all modifiers and capabilities
  • [ ] Review existing src/test/java/com/squareup/javapoet/CodeWriterTest.java and ParameterSpecTest.java
  • [ ] Add tests for varargs parameters with type variables
  • [ ] Add tests for parameters with multiple annotations
  • [ ] Add tests for final parameters combined with other modifiers
  • [ ] Run full test suite to ensure no regressions

Add integration tests for JavaFile.writeTo() with nested static classes and inner types

FileWritingTest.java likely has basic file-writing tests, but generating complex nested type hierarchies (static inner classes, anonymous types, local classes) is a common use case that may lack coverage. This matters because incorrect nesting can produce uncompilable code. Add tests that verify the generated .java files can actually compile.

  • [ ] Review src/test/java/com/squareup/javapoet/FileWritingTest.java for nested type coverage
  • [ ] Review src/main/java/com/squareup/javapoet/TypeSpec.java for nested class support
  • [ ] Create test that generates a TypeSpec with multiple levels of nested static classes
  • [ ] Create test that generates inner non-static classes
  • [ ] Use compile-testing dependency (already in pom.xml) to verify generated code compiles
  • [ ] Add assertions that check proper indentation and source structure
  • [ ] Verify tests run with mvn clean test

🌿Good first issues

  • Add test coverage for edge case in WildcardTypeName.java—check if src/test/java/com/squareup/javapoet/ has corresponding WildcardTypeNameTest.java. If missing, write tests for ? extends Foo and ? super Bar bounds.
  • Enhance LineWrapper.java javadoc—it's referenced in JavaFile but lacks examples. Add concrete code sample showing line-wrapping behavior with 80-char width and nested generics.
  • Add integration test in src/test/java/com/squareup/javapoet/FileReadingTest.java or FileWritingTest.java for round-trip: generate a .java file, parse it with compile-testing, verify it matches the input spec (catch model-to-source fidelity bugs).

Top contributors

Click to expand

📝Recent commits

Click to expand
  • b9017a9 — Add ‘diff’ to the diff block (swankjesse)
  • a5ddb12 — Merge pull request #1014 from square/squarejesse-patch-1 (swankjesse)
  • cdb1f2d — consistent syntax (swankjesse)
  • 9d93c79 — Deprecate JavaPoet (swankjesse)
  • e7429cb — Merge pull request #1013 from square/renovate/org.apache.maven.plugins-maven-checkstyle-plugin-3.x (JakeWharton)
  • 4286e31 — Update dependency org.apache.maven.plugins:maven-checkstyle-plugin to v3.5.0 (renovate[bot])
  • 05bb87b — Merge pull request #1009 from square/renovate/truth.version (JakeWharton)
  • 66953b8 — Update dependency com.google.truth:truth to v1.4.4 (renovate[bot])
  • f27ad04 — Merge pull request #1008 from square/renovate/truth.version (JakeWharton)
  • 8d60c62 — Update dependency com.google.truth:truth to v1.4.3 (renovate[bot])

🔒Security observations

JavaPoet is a code generation library with minimal direct security risks in its core functionality. The primary concern is that the project is officially deprecated and no longer actively maintained, which poses a long-term security risk. Dependencies are relatively minimal and stable (JUnit, Truth, Compile Testing). No hardcoded secrets, injection vulnerabilities, or infrastructure misconfiguration issues were detected in the provided file structure. The library itself does not handle sensitive data or network operations, reducing the attack surface. Recommend migration to Palantir's maintained fork for production use.

  • Medium · Deprecated Project with Limited Maintenance — README.md, Project Status. JavaPoet has been officially deprecated as of 2020-10-10 and is no longer actively maintained by Square. This means security vulnerabilities and bugs may not be fixed in a timely manner. Fix: Consider migrating to Palantir's JavaPoet fork (com.palantir.javapoet:javapoet) which actively maintains support for the latest Java language features and security patches.
  • Low · Outdated Compile Testing Dependency — pom.xml - compile-testing dependency. The compile-testing dependency version 0.21.0 is relatively old and may contain unpatched vulnerabilities. This is only used in test scope, reducing the risk, but should still be monitored. Fix: Check for available updates to compile-testing and evaluate upgrading to the latest stable version. Review the Google Compile Testing changelog for security fixes.
  • Low · JUnit 4 Usage (Legacy Test Framework) — pom.xml - junit dependency. The project uses JUnit 4.13.2, which is older than JUnit 5. While not a direct security vulnerability, using older test frameworks may miss security-focused testing improvements in newer versions. Fix: Consider evaluating migration to JUnit 5 (Jupiter) for improved testing capabilities and maintenance, though this is not critical for this library.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · square/javapoet — RepoPilot