Skip to content

Conversation

@keys-i
Copy link

@keys-i keys-i commented Dec 22, 2025

This PR adds a comprehensive Java snippets pack for the Zed IDE to highlight common Java patterns and speed up development.

Stuff added

New snippet scopes included:

File Scope What it covers
java.json Java Core Java, collections/streams, Optional, concurrency, IO/NIO, HttpClient, Jackson/Gson, logging, JUnit5, Mockito, Spring Boot, JPA, Lombok, common patterns
groovy.json Gradle (Groovy) build.gradle helpers
kotlin.json Gradle (Kotlin DSL) build.gradle.kts helpers
xml.json Maven pom.xml starter

Motivation

Zed’s snippet workflow is fast, but Java dev typically spans:

  • core language structures (classes, methods, overrides, guards)
  • testing (JUnit5, parameterized tests, Mockito, AssertJ)
  • backend scaffolding (Spring Boot controllers/services, JPA entity annotations)
  • build tooling (Gradle/Maven) + deployment (Docker) + config (YAML)

This pack keeps those at your fingertips with consistent prefixes and tab-stops.

Notes

  • Uses short, consistent prefixes (j* for Java, sb* for Spring, m* for Mockito, etc.) to avoid polluting autocomplete.
  • Uses $1, ${1:default} and $0 tab-stops throughout for quick field-filling.
  • Keeps snippets fully-qualified in some cases to reduce required imports during quick prototyping (can be refined later if the repo prefers import-first style).

Test plan

  • Open a .java file in Zed
  • Trigger snippet expansion for:
    • jmain
    • junit
    • sbrest
    • jpaentity
  • Verify tab-stops advance correctly and $0 places cursor at expected location
  • Validate JSON files parse (no trailing commas / invalid JSON)

Checklist

  • JSON files are valid
  • Prefixes are unique enough to avoid collisions
  • Snippets are grouped by scope and named clearly
  • [x ] README/docs updated if required by repo conventions

Signed-off-by: Keys <70819367+keys-i@users.noreply.github.com>
Signed-off-by: Keys <70819367+keys-i@users.noreply.github.com>
Signed-off-by: Keys <70819367+keys-i@users.noreply.github.com>
Signed-off-by: Keys <70819367+keys-i@users.noreply.github.com>
…ng extra

Signed-off-by: Keys <70819367+keys-i@users.noreply.github.com>
Signed-off-by: Keys <70819367+keys-i@users.noreply.github.com>
Signed-off-by: Keys <70819367+keys-i@users.noreply.github.com>
Signed-off-by: Keys <70819367+keys-i@users.noreply.github.com>
Signed-off-by: Keys <70819367+keys-i@users.noreply.github.com>
@cla-bot
Copy link

cla-bot bot commented Dec 22, 2025

We require contributors to sign our Contributor License Agreement, and we don't have @keys-i on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'.

Signed-off-by: Keys <70819367+keys-i@users.noreply.github.com>
… and moved java snippets to snippets/

Signed-off-by: Keys <70819367+keys-i@users.noreply.github.com>
@cla-bot
Copy link

cla-bot bot commented Dec 22, 2025

We require contributors to sign our Contributor License Agreement, and we don't have @keys-i on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'.

Signed-off-by: Keys <70819367+keys-i@users.noreply.github.com>
@cla-bot
Copy link

cla-bot bot commented Dec 22, 2025

We require contributors to sign our Contributor License Agreement, and we don't have @keys-i on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'.

Signed-off-by: Keys <70819367+keys-i@users.noreply.github.com>
@cla-bot cla-bot bot added the cla-signed label Dec 22, 2025
@acardonna
Copy link
Contributor

acardonna commented Dec 22, 2025

First of all, I'm sure you put a lot of work into this and have only good intentions, so I'm sorry if this doesn't come across as I want it to. I'm just curious as to why you didn't consider making this an extension? I haven't seen any other language extension bake snippets directly into it, and I also think that's not a good idea, since at least for me, this is a highly subjective feature that you can decide to implement either by defining your own snippets (see the snippets docu) or by downloading your favorite snippets extensions for your language. Having the language extension decide this for the user doesn't seem right to me. Again, I think this is a pretty good idea, but I do think an extension would be the ideal approach to this. What do you think?

Edit: Maybe I'm missing something and user-defined snippets will take precedence over this? I don't know. Anyway, just so you know, I don't have a say in this, I'm just giving my humble opinion :)

@keys-i
Copy link
Author

keys-i commented Dec 22, 2025

Fair point, and thanks for the thoughtful tone.

I bundled snippets because the Ruby language extension already ships its own snippets, so I took that as precedent and figured a solid Java baseline would be helpful too. Java has a lot of repetitive scaffolding like tests, classes, streams, and Spring style patterns.

That said, I agree with you that snippets are subjective, and a separate snippets extension is a cleaner model. Language pack for language support, snippet pack for opinionated productivity.

On your edit, user snippets should override shipped ones, but you are right that this should be explicit and guaranteed.

So yes, I still think the idea is useful, but I am happy to move this into a dedicated Java snippets extension, or keep only a small core set in the language pack.

"Valentine Briese <valentinegb@icloud.com>",
"Samuser107 L.Longheval <samuser107@gmail.com>",
"Yury Abykhodau <abehodau@gmail.com>",
"Keys <70819367+keys-i@users.noreply.github.com>"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are not actually updating this field. We should consider to change it into a more inclusive Java repo contributors, especially because by now, if everyone who has ever contributed added their name this list would be very long.

Copy link
Author

@keys-i keys-i Dec 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, since we’re not maintaining this field and an exhaustive list would grow indefinitely, I think we should make it inclusive and low-maintenance. Something like authors = ["The <Repo/Project> contributors"] (e.g., “The Deno authors”) works well and still gives credit broadly, while GitHub’s contributor history remains the source of truth for the full list.

]
description = "Java support."
repository = "https://github.com/zed-extensions/java"
snippets = "./snippets/java.json"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are other snippets (groovy, kotlin, xml) linked?

Copy link
Author

@keys-i keys-i Dec 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They aren’t linked via the snippets field, I can only point snippets at a single JSON file because it doesn’t accept a list of paths. So it’s effectively snippets = "path" (one file only), not something like multiple snippet files.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would that help here? I was bothered by that also a bit and could look into making this accept multiple paths finally

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think that would help here.

If we can accept multiple snippet paths (or multiple packs) instead of forcing everything through a single JSON, it becomes much easier to keep “typed” vs “untyped / vendor” sources separated and avoid Unknown poisoning everything. I was bothered by that too.

I’d genuinely love to help you make it multi-path and get it working end to end. If you can point me at where the config gets parsed and where the snippet loader resolves snippets = "path", I can take a look and put up a PR to support something like:

  • snippets = ["path1", "path2", ...] (or)
  • snippets_paths = [...]

and then merge the loaded snippets deterministically (with clear precedence rules). Happy to do the legwork and iterate with you on the design.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very long list of snippets. Are they coming from a known source? If so it would be nice to reference that so that we can actually keep the two up to date.

Copy link
Author

@keys-i keys-i Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These snippets aren’t copied from a single upstream list; they’re a curated pack assembled by

  1. porting the “standard” scaffolds used in common editor snippet packs where they exist, and
  2. aligning the templates to the canonical examples shown in the official language/library documentation below so they can be kept in sync over time.
Snippet How I got them Source
Tabstops / placeholders ($1, $0, ${1:default}) Used the VS Code snippet syntax spec (Zed-compatible placeholder conventions) VS Code – User Defined Snippets
Java language “modern feature” templates Mirrored the official JEP examples/semantics for feature-specific snippet shapes JEP 395 Records
JEP 409 Sealed Classes
JEP 361 Switch Expressions
JEP 378 Text Blocks
Java standard library usage snippets Lifted canonical API usage patterns from Java SE API docs HttpClient (Java SE API)
JUnit test templates Used the JUnit 5 user guide patterns (nested tests, parameterized tests, lifecycle) JUnit 5 User Guide
JUnit – Parameterized classes/tests
Mockito mocking templates Used Mockito API/Javadoc patterns (e.g., verify, captors) Mockito (API)
ArgumentCaptor (Javadoc)
AssertJ assertion templates Used AssertJ official docs + the Assertions entrypoint patterns AssertJ docs
Assertions (Javadoc)
Spring MVC controller templates Used Spring Framework reference docs for request mapping shapes Spring MVC – @RequestMapping
Spring Boot bootstrap templates Used Spring Boot reference docs for app bootstrap + @SpringBootApplication Spring Boot – SpringApplication
Spring Boot – @SpringBootApplication
Lombok templates Used Lombok official feature pages for @Data / @Builder Lombok – @Data
Lombok – @Builder
Jackson templates Used Jackson ObjectMapper API/Javadoc as the source of truth ObjectMapper (Javadoc)
JPA / persistence templates Used Jakarta EE tutorial sections that define entity + primary key patterns Jakarta EE Tutorial – Persistence intro
Bean validation templates Used Jakarta EE tutorial + Jakarta constraints API pages Jakarta EE Tutorial – Bean Validation
jakarta.validation.constraints (API)
Logging templates Used SLF4J manual for parameterized logging patterns SLF4J Manual
Gradle testing snippets Used Gradle’s official Java testing docs (+ useJUnitPlatform) Gradle – Testing in Java/JVM
Gradle DSL – useJUnitPlatform
Maven testing/build snippets Used Maven plugin docs for Surefire + Compiler config baselines Maven Surefire
Maven Compiler Plugin

Treat these upstreams as authoritative. If it conflicts with them, our snippets are wrong.

Copy link
Author

@keys-i keys-i Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about the sprawl here - Java doesn’t really have a single “one extension to rule them all” upstream the way some ecosystems do. In VS Code it’s an ecosystem (JDTLS + separate Spring/test/build tooling), so the snippet pack ends up referencing multiple authoritative sources rather than one canonical repo.

Comment on lines +219 to +228
"System.out.println": {
"prefix": "sout",
"body": ["System.out.println(${1:msg});", "$0"],
"description": "Print to stdout."
},
"System.err.println": {
"prefix": "serr",
"body": ["System.err.println(${1:msg});", "$0"],
"description": "Print to stderr."
},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sysout and syserr are already offered by jdtls, as above, if these snippets are coming from a known source it would make sense to keep them otherwise these two could create some conflicts or rather, redundancy.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point , sout / serr are already provided by JDTLS, so including them here is redundant and could cause noisy/conflicting completions. I’ll drop those two from the pack and keep this set focused on snippets that aren’t covered by the language server. The upstream references are in my previous comment.

@keys-i keys-i requested a review from tartarughina December 23, 2025 00:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants