From 0702da9e1baeb9eca9775e5dbfcf5d09e88daab1 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 3 Aug 2026 09:16:21 +0000
Subject: [PATCH 1/5] Document AutoRest Java customizations
Co-authored-by: XiaofeiCao <92354331+XiaofeiCao@users.noreply.github.com>
---
docs/contributor/README.md | 1 +
.../autorest-java-customization.md | 172 ++++++++++++++++++
docs/contributor/typespec-quickstart.md | 2 +
3 files changed, 175 insertions(+)
create mode 100644 docs/contributor/autorest-java-customization.md
diff --git a/docs/contributor/README.md b/docs/contributor/README.md
index 9f9a26aa7405..f449d9b4f7c9 100644
--- a/docs/contributor/README.md
+++ b/docs/contributor/README.md
@@ -28,6 +28,7 @@ If you are a **consumer** of the SDK looking for usage guidance, start at the [U
| [Versioning](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/versioning.md) | `version_client.txt`, dependency tags, incrementing versions |
| [Adding a Module](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/adding-a-module.md) | Create a new SDK module: dir structure, POM, versioning, CODEOWNERS |
| [TypeSpec Quickstart](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/typespec-quickstart.md) | End-to-end workflow: generate → build → test → release |
+| [AutoRest Java Customization](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/autorest-java-customization.md) | Customize generated Java code when TypeSpec cannot express the required behavior |
| [Writing Performance Tests](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/performance-tests.md) | Set up and run `perf-test-core` benchmarks |
| [JavaDoc & Code Snippets](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/javadocs.md) | Javadoc standards and codesnippet-maven-plugin workflow |
| [Access Helpers](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/access-helpers.md) | Cross-package internal access without public APIs |
diff --git a/docs/contributor/autorest-java-customization.md b/docs/contributor/autorest-java-customization.md
new file mode 100644
index 000000000000..cd3cb578d5a0
--- /dev/null
+++ b/docs/contributor/autorest-java-customization.md
@@ -0,0 +1,172 @@
+# AutoRest Java Customization
+
+The `azure-autorest-customization` package provides APIs to safely customize generated Java code for cases that
+AutoRest cannot represent directly. It uses the Eclipse language server to validate the Java code it changes.
+
+## Before you customize
+
+First consider whether the change belongs in TypeSpec (`client.tsp`). TypeSpec customizations are cleaner and persist
+through regeneration. See the [TypeSpec Client Customizations Reference](https://github.com/Azure/azure-sdk-for-java/blob/main/eng/common/knowledge/customizing-client-tsp.md) for decorators such as `@@clientName` and `@@access`.
+
+Use Java code customizations only when TypeSpec cannot express the required behavior.
+
+## Set up a customization project
+
+Create a Maven project that depends on `azure-autorest-customization`:
+
+```xml
+
+ com.azure.tools
+ azure-autorest-customization
+ 1.0.0-beta.11
+
+```
+
+Create a class that extends `com.azure.autorest.customization.Customization` and overrides
+`void customize(LibraryCustomization, Logger)`. The `LibraryCustomization` parameter is the entry point for changing
+generated Java code before it is written to disk.
+
+```java
+@Override
+public void customize(LibraryCustomization customization, Logger logger) {
+ customization.getClass("com.azure.myservice.models", "Foo")
+ .customizeAst(ast -> ast.getClassByName("Foo")
+ .ifPresent(clazz -> clazz.addMarkerAnnotation("Deprecated")));
+}
+```
+
+Configure the generator to use the class:
+
+```yaml
+customization-class: src/main/java/MyCustomization.java
+```
+
+## Navigate generated code
+
+Start with `LibraryCustomization`, then navigate to a package or class with `getClass(packageName, className)`.
+`LibraryCustomization`, `PackageCustomization`, and `ClassCustomization` provide the primary navigation APIs.
+Use `customizeAst` to change the JavaParser AST for the selected source file. Add imports with
+`ast.addImport(...)` whenever the new code references a type not already imported.
+
+## Supported customizations
+
+The following common changes can be made through the JavaParser AST:
+
+| Customization | Typical AST operation |
+|---|---|
+| Change a class modifier | `ClassOrInterfaceDeclaration.setModifiers(...)` |
+| Change a method modifier | `MethodDeclaration.setModifiers(...)` |
+| Change a method return type or body | `MethodDeclaration.setType(...)` and `setBody(...)` |
+| Change a class supertype | Clear and add `ClassOrInterfaceType` extended types |
+| Add or remove a class or method annotation | `addMarkerAnnotation(...)` or remove the matching annotation node |
+| Add a field default value | `VariableDeclarator.setInitializer(...)` |
+| Add getter and setter methods | `ClassOrInterfaceDeclaration.addMethod(...)` |
+| Rename an enum member | `EnumConstantDeclaration.setName(...)` |
+| Update class or method Javadoc | `setJavadocComment(...)` |
+| Add or remove Javadoc tags | Update the `Javadoc` returned by `getJavadoc()` |
+
+### Change a method modifier
+
+```java
+@Override
+public void customize(LibraryCustomization customization, Logger logger) {
+ customization.getClass("com.azure.myservice.models", "Foo").customizeAst(ast -> ast.getClassByName("Foo")
+ .ifPresent(clazz -> clazz.getMethodsByName("getBar")
+ .forEach(method -> method.setModifiers(Modifier.Keyword.PRIVATE))));
+}
+```
+
+### Change a method return type
+
+When changing a return type, update both the declared type and method body. Add an import for the replacement type.
+
+```java
+@Override
+public void customize(LibraryCustomization customization, Logger logger) {
+ customization.getClass("com.azure.myservice.models", "Foo").customizeAst(ast -> {
+ ast.addImport(UUID.class);
+ ast.getClassByName("Foo").ifPresent(clazz -> clazz.getMethodsByName("getId").forEach(method -> {
+ method.setType("UUID");
+ method.setBody(StaticJavaParser.parseBlock("{ return UUID.fromString(this.id); }"));
+ }));
+ });
+}
+```
+
+For a method originally returning `void`, provide the complete return expression. To change a method to return
+`void`, set its body appropriately and do not add a return value.
+
+### Change a supertype
+
+```java
+@Override
+public void customize(LibraryCustomization customization, Logger logger) {
+ customization.getClass("com.azure.myservice.models", "Foo").customizeAst(ast -> ast.getClassByName("Foo")
+ .ifPresent(clazz -> {
+ ast.addImport("com.azure.myservice.models.Bar1");
+ clazz.getExtendedTypes().clear();
+ clazz.addExtendedType(new ClassOrInterfaceType(null, "Bar1"));
+ }));
+}
+```
+
+### Add a field default value
+
+```java
+@Override
+public void customize(LibraryCustomization customization, Logger logger) {
+ customization.getClass("com.azure.myservice.models", "Foo").customizeAst(ast -> ast.getClassByName("Foo")
+ .flatMap(clazz -> clazz.getFieldByName("bar"))
+ .ifPresent(field -> field.getVariables().forEach(variable -> {
+ if ("bar".equals(variable.getNameAsString())) {
+ variable.setInitializer("\"bar\"");
+ }
+ })));
+}
+```
+
+### Generate accessor methods
+
+```java
+@Override
+public void customize(LibraryCustomization customization, Logger logger) {
+ customization.getClass("com.azure.myservice.models", "Foo").customizeAst(ast -> ast.getClassByName("Foo")
+ .ifPresent(clazz -> {
+ clazz.addMethod("isActive", Modifier.Keyword.PUBLIC).setType("boolean")
+ .setBody(StaticJavaParser.parseBlock("{ return this.active; }"));
+ clazz.addMethod("setActive", Modifier.Keyword.PUBLIC).setType("Foo")
+ .addParameter("boolean", "active")
+ .setBody(StaticJavaParser.parseBlock("{ this.active = active; return this; }"));
+ }));
+}
+```
+
+### Update Javadoc
+
+Set a complete description with `setJavadocComment`. For parameter, return, and exception tags, get the existing
+Javadoc and add a block tag:
+
+```java
+method.getJavadoc().ifPresent(javadoc -> method.setJavadocComment(
+ javadoc.addBlockTag("param", "active", "whether the Foo is active")));
+```
+
+Use `return` for a return-value tag and `throws` with the exception type and description for an exception tag.
+
+## Troubleshooting
+
+### AutoRest reports “Unable to format output file”
+
+Customized Java code likely contains a syntax error.
+
+1. Add the `skip-formatting` flag to bypass formatting while diagnosing the generated source.
+2. Compile or inspect the generated code to find the error.
+3. Fix the customization code, or report a defect in `customization-base` if it caused the invalid code.
+4. Remove `skip-formatting`.
+
+## Developer note
+
+`azure-autorest-customization` sends generated source files to an Eclipse language server for IDE-like analysis. Its
+dummy `pom.xml` in `src/main/resources` supplies the language server dependencies. When generator changes cause
+customizations to fail, verify that this POM contains all required dependencies; otherwise processing can fall back to
+less reliable text-based behavior.
diff --git a/docs/contributor/typespec-quickstart.md b/docs/contributor/typespec-quickstart.md
index c482c82b5fde..b5d787bbe5a5 100644
--- a/docs/contributor/typespec-quickstart.md
+++ b/docs/contributor/typespec-quickstart.md
@@ -101,6 +101,8 @@ Set `partial-update: true` in `tspconfig.yaml` emitter options. TypeSpec-Java wi
customization-class: customization/src/main/java/MyCustomization.java
```
+See [AutoRest Java Customization](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/autorest-java-customization.md) for guidance on writing AST-based Java customizations.
+
---
## 5. Improve Documentation
From c45fce6df5e10c4f678baf6b870f6302b5dceee3 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 3 Aug 2026 09:26:27 +0000
Subject: [PATCH 2/5] Rename customization guide for TypeSpec Java
Co-authored-by: XiaofeiCao <92354331+XiaofeiCao@users.noreply.github.com>
---
docs/contributor/README.md | 2 +-
.../sdk-generation-pipeline-troubleshooting.md | 2 +-
...ization.md => typespec-java-customization.md} | 16 ++++++++--------
docs/contributor/typespec-quickstart.md | 2 +-
4 files changed, 11 insertions(+), 11 deletions(-)
rename docs/contributor/{autorest-java-customization.md => typespec-java-customization.md} (90%)
diff --git a/docs/contributor/README.md b/docs/contributor/README.md
index f449d9b4f7c9..1de726c5377a 100644
--- a/docs/contributor/README.md
+++ b/docs/contributor/README.md
@@ -28,7 +28,7 @@ If you are a **consumer** of the SDK looking for usage guidance, start at the [U
| [Versioning](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/versioning.md) | `version_client.txt`, dependency tags, incrementing versions |
| [Adding a Module](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/adding-a-module.md) | Create a new SDK module: dir structure, POM, versioning, CODEOWNERS |
| [TypeSpec Quickstart](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/typespec-quickstart.md) | End-to-end workflow: generate → build → test → release |
-| [AutoRest Java Customization](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/autorest-java-customization.md) | Customize generated Java code when TypeSpec cannot express the required behavior |
+| [TypeSpec Java Customization](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/typespec-java-customization.md) | Customize generated Java code when TypeSpec cannot express the required behavior |
| [Writing Performance Tests](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/performance-tests.md) | Set up and run `perf-test-core` benchmarks |
| [JavaDoc & Code Snippets](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/javadocs.md) | Javadoc standards and codesnippet-maven-plugin workflow |
| [Access Helpers](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/access-helpers.md) | Cross-package internal access without public APIs |
diff --git a/docs/contributor/sdk-generation-pipeline-troubleshooting.md b/docs/contributor/sdk-generation-pipeline-troubleshooting.md
index 6b54bcf646da..30e2d3ba8a06 100644
--- a/docs/contributor/sdk-generation-pipeline-troubleshooting.md
+++ b/docs/contributor/sdk-generation-pipeline-troubleshooting.md
@@ -131,7 +131,7 @@ please check whether it causes failure, and fix them before apiview.
> - *generated code*: produced by the generator; API surface may change when the spec or generator changes, which can break compilation.
> - *customization code*: maintained by SDK developers; commonly wired via `customization-class` and preserved during regeneration with `partial-update: true`.
>
-> Reference: autorest.java customization-base: https://github.com/Azure/autorest.java/tree/main/customization-base
+> Reference: [TypeSpec Java Customization](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/typespec-java-customization.md)
**Prerequisites for customization:** When adding customization code, two options must be set in `tspconfig.yaml`:
```yaml
diff --git a/docs/contributor/autorest-java-customization.md b/docs/contributor/typespec-java-customization.md
similarity index 90%
rename from docs/contributor/autorest-java-customization.md
rename to docs/contributor/typespec-java-customization.md
index cd3cb578d5a0..bb6dbc19d4ab 100644
--- a/docs/contributor/autorest-java-customization.md
+++ b/docs/contributor/typespec-java-customization.md
@@ -1,7 +1,7 @@
-# AutoRest Java Customization
+# TypeSpec Java Customization
The `azure-autorest-customization` package provides APIs to safely customize generated Java code for cases that
-AutoRest cannot represent directly. It uses the Eclipse language server to validate the Java code it changes.
+TypeSpec Java cannot represent directly. It uses the Eclipse language server to validate the Java code it changes.
## Before you customize
@@ -155,18 +155,18 @@ Use `return` for a return-value tag and `throws` with the exception type and des
## Troubleshooting
-### AutoRest reports “Unable to format output file”
+### TypeSpec Java reports “Unable to format output file”
Customized Java code likely contains a syntax error.
1. Add the `skip-formatting` flag to bypass formatting while diagnosing the generated source.
2. Compile or inspect the generated code to find the error.
-3. Fix the customization code, or report a defect in `customization-base` if it caused the invalid code.
+3. Fix the customization code, or report a defect in the TypeSpec Java generator if it produced invalid code.
4. Remove `skip-formatting`.
## Developer note
-`azure-autorest-customization` sends generated source files to an Eclipse language server for IDE-like analysis. Its
-dummy `pom.xml` in `src/main/resources` supplies the language server dependencies. When generator changes cause
-customizations to fail, verify that this POM contains all required dependencies; otherwise processing can fall back to
-less reliable text-based behavior.
+TypeSpec Java sends generated source files to an Eclipse language server for IDE-like analysis. Its dummy `pom.xml` in
+`src/main/resources` supplies the language server dependencies. When generator changes cause customizations to fail,
+verify that this POM contains all required dependencies; otherwise processing can fall back to less reliable text-based
+behavior.
diff --git a/docs/contributor/typespec-quickstart.md b/docs/contributor/typespec-quickstart.md
index b5d787bbe5a5..c2d0878c0c90 100644
--- a/docs/contributor/typespec-quickstart.md
+++ b/docs/contributor/typespec-quickstart.md
@@ -101,7 +101,7 @@ Set `partial-update: true` in `tspconfig.yaml` emitter options. TypeSpec-Java wi
customization-class: customization/src/main/java/MyCustomization.java
```
-See [AutoRest Java Customization](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/autorest-java-customization.md) for guidance on writing AST-based Java customizations.
+See [TypeSpec Java Customization](https://github.com/Azure/azure-sdk-for-java/blob/main/docs/contributor/typespec-java-customization.md) for guidance on writing AST-based Java customizations.
---
From 245db22883a3969dd04ea757f750a72778f72fea Mon Sep 17 00:00:00 2001
From: "Xiaofei Cao (from Dev Box)"
Date: Tue, 4 Aug 2026 11:41:59 +0800
Subject: [PATCH 3/5] address comments
---
docs/contributor/typespec-java-customization.md | 16 +++-------------
1 file changed, 3 insertions(+), 13 deletions(-)
diff --git a/docs/contributor/typespec-java-customization.md b/docs/contributor/typespec-java-customization.md
index bb6dbc19d4ab..39855d26c9cb 100644
--- a/docs/contributor/typespec-java-customization.md
+++ b/docs/contributor/typespec-java-customization.md
@@ -1,7 +1,7 @@
# TypeSpec Java Customization
The `azure-autorest-customization` package provides APIs to safely customize generated Java code for cases that
-TypeSpec Java cannot represent directly. It uses the Eclipse language server to validate the Java code it changes.
+TypeSpec Java cannot represent directly. Customizations use JavaParser ASTs through `ClassCustomization.customizeAst`.
## Before you customize
@@ -155,18 +155,8 @@ Use `return` for a return-value tag and `throws` with the exception type and des
## Troubleshooting
-### TypeSpec Java reports “Unable to format output file”
+### TypeSpec Java reports “Failed to format file: ``. File content: ``.”
Customized Java code likely contains a syntax error.
-1. Add the `skip-formatting` flag to bypass formatting while diagnosing the generated source.
-2. Compile or inspect the generated code to find the error.
-3. Fix the customization code, or report a defect in the TypeSpec Java generator if it produced invalid code.
-4. Remove `skip-formatting`.
-
-## Developer note
-
-TypeSpec Java sends generated source files to an Eclipse language server for IDE-like analysis. Its dummy `pom.xml` in
-`src/main/resources` supplies the language server dependencies. When generator changes cause customizations to fail,
-verify that this POM contains all required dependencies; otherwise processing can fall back to less reliable text-based
-behavior.
+Inspect the source shown after `File content:` to locate the malformed code, then fix the customization and regenerate SDK.
From 83cf6efafefc346dcccbdc4f5344b8a921087951 Mon Sep 17 00:00:00 2001
From: Xiaofei Cao <92354331+XiaofeiCao@users.noreply.github.com>
Date: Tue, 4 Aug 2026 11:57:30 +0800
Subject: [PATCH 4/5] apply copilot review for customization example
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---
docs/contributor/typespec-java-customization.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/contributor/typespec-java-customization.md b/docs/contributor/typespec-java-customization.md
index 39855d26c9cb..160b54ac2d95 100644
--- a/docs/contributor/typespec-java-customization.md
+++ b/docs/contributor/typespec-java-customization.md
@@ -38,7 +38,7 @@ public void customize(LibraryCustomization customization, Logger logger) {
Configure the generator to use the class:
```yaml
-customization-class: src/main/java/MyCustomization.java
+customization-class: customization/src/main/java/MyCustomization.java
```
## Navigate generated code
From 12252bfd9fdb809b50b145302f769d7f53128d92 Mon Sep 17 00:00:00 2001
From: "Xiaofei Cao (from Dev Box)"
Date: Tue, 4 Aug 2026 14:00:15 +0800
Subject: [PATCH 5/5] use diff for customization-class configuration
---
docs/contributor/typespec-java-customization.md | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/docs/contributor/typespec-java-customization.md b/docs/contributor/typespec-java-customization.md
index 160b54ac2d95..05c3f102c0c9 100644
--- a/docs/contributor/typespec-java-customization.md
+++ b/docs/contributor/typespec-java-customization.md
@@ -37,8 +37,11 @@ public void customize(LibraryCustomization customization, Logger logger) {
Configure the generator to use the class:
-```yaml
-customization-class: customization/src/main/java/MyCustomization.java
+```diff
+ "@azure-tools/typespec-java":
+ emitter-output-dir: "{output-dir}/{service-dir}/azure-contoso-widgetmanager"
+ namespace: com.azure.contoso.widgetmanager
++ customization-class: customization/src/main/java/MyCustomization.java
```
## Navigate generated code