بنقرة واحدة
format-source
Format source files to align with Liferay's coding standards.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Format source files to align with Liferay's coding standards.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Shrink a Liferay component's Poshi test suite by merging overlapping tests. Use when the user asks to reduce, merge, or clean up Poshi tests for a @component-name.
Start work on a Jira ticket.
Use when creating a Git worktree for parallel Liferay development, setting up a worktree bundle after ant all, checking which ports a worktree uses, listing all worktrees and their status, or tearing down a worktree. Covers the full lifecycle from Git worktree add through cleanup.
Create a GitHub pull request for the current branch, transition the corresponding Jira ticket to review, and record the PR link on the ticket. Use when the user asks to create a PR, send a PR, or invokes /pr.
Add a new rule to the format-source skill, derived from a Git commit.
Format a Markdown file to match Liferay conventions — frontmatter order, Title Case headings, braced shell variables, long-form CLI flags, and professional prose. Use when the user asks to format, clean up, polish, or copy-edit a Markdown file destined for the Liferay repository.
| description | Format source files to align with Liferay's coding standards. |
| name | format-source |
All the code is strictly formatted using the source formatter (Java, JavaScript, JSON, JSP, Markdown, properties, shell, XML, YAML, and others). This is how it works:
Run for a specific module:
cd <module-root> && <gradlew> formatSource
Run across the entire codebase:
cd <repo-root>/portal-impl && ant format-source-current-branch
ant format-source-current-branch only inspects committed files, so run it after creating the commit, and amend any formatter changes or fixes into that commit.
In both cases, if there are issues to be fixed, the formatter will list them. Fix them.
In addition to the automatic formatter, there is a set of manual rules that the formatter does not catch. The full workflow is to run the formatter, apply the manual rules, then rerun the formatter to clean up any fallout from the manual edits.
Skip generated files. The automatic formatter already does this via BaseSourceProcessor.hasGeneratedTag; apply the same rule to manual edits. A file is generated when it contains any of these unquoted markers:
@generated — Service Builder, REST Builder, taglib generator (Java, by far the most common; ~18k files)
$ANTLR — ANTLR-generated lexers and parsers
# This is a generated file. — generated scripts
## Autogenerated — generated Markdown and config
These files are overwritten on the next build, so manual edits are lost and only pollute the diff.
Why: Consistent method order in chained calls makes it easier to scan for a specific call and reduces churn when new methods are added to the chain.
Examples:
Foo foo = builder.start(
arg
-).gamma(
- gammaArg
).alpha(
alphaArg
).beta(
betaArg
+).gamma(
+ gammaArg
).build();
Why: Consistent parameter order makes call sites easier to scan and reduces churn when new parameters are added.
Examples:
private void process(
- String charlie, long alpha, String beta,
+ long alpha, String beta, String charlie,
Object delta) {
Why: Consistent assertion order makes test failures easier to locate and reduces churn when new cases are added.
Examples:
Assert.assertEquals(1L, map.get("apple"));
-Assert.assertEquals(3L, map.get("cherry"));
Assert.assertEquals(2L, map.get("banana"));
+Assert.assertEquals(3L, map.get("cherry"));
Why: Consistent declaration order makes it easier to find a variable and reduces churn when new locals are added.
Examples:
-Map<X, Y> beta = new HashMap<>();
-
boolean alpha = check();
+Map<X, Y> beta = new HashMap<>();
Why: A type suffix makes the variable's type readable at the use site and prevents a generic local from shadowing a same-named string key, field, or call argument in scope.
Examples:
Strings and other reference types like Date, JSONObject get a type suffix.
-String foo = result.toString();
+String fooString = result.toString();
int, long, boolean keep descriptive names without a type suffix.
-int countInt = items.size();
-long timeLong = System.currentTimeMillis();
-boolean enabledBoolean = config.isEnabled();
+int count = items.size();
+long time = System.currentTimeMillis();
+boolean enabled = config.isEnabled();
Lists prefer a plural name; the List suffix is acceptable when no natural plural exists.
-List<Item> itemList = repository.findAll();
+List<Item> items = repository.findAll();
Maps prefer a descriptive name; the Map suffix is acceptable when no natural descriptor exists.
-Map<String, Item> itemMap = loadIndex();
+Map<String, Item> itemsByKey = loadIndex();
Why: Treating acronyms as fully uppercase tokens keeps method, field, and variable names visually consistent with the surrounding API and avoids drift between camelCase and CamelCase variants for the same concept.
Examples:
-public String getUrl() {
+public String getURL() {
return _url;
}
-foo.getHtmlContent();
-bar.parseXmlString();
+foo.getHTMLContent();
+bar.parseXMLString();
Why: Wrapping literal identifiers, header values, content types, and similar tokens in double quotes inside log and exception messages separates the literal from the surrounding prose, so a reader can tell at a glance which words come from the data and which from the sentence.
Examples:
throw new IllegalArgumentException(
- "Request body has no application/json content");
+ "Request body has no \"application/json\" content");
-_log.warn("Missing header X-Custom-Header for request");
+_log.warn("Missing header \"X-Custom-Header\" for request");
Use escaped double quotes, not single quotes, to wrap the token.
-throw new IllegalArgumentException("Missing 'paths' object");
+throw new IllegalArgumentException("Missing \"paths\" object");
Why: When a method scope holds a single int index returned from indexOf or similar, naming it plainly index is shorter than a qualified name and matches the dominant convention; reuse the same index slot for sequential lookups in the same scope rather than introducing parallel qualified names.
Examples:
-int spaceIndex = endpoint.indexOf(' ');
+int index = endpoint.indexOf(' ');
-String prefix = endpoint.substring(0, spaceIndex);
-String suffix = endpoint.substring(spaceIndex + 1);
+String prefix = endpoint.substring(0, index);
+String suffix = endpoint.substring(index + 1);
When the value is reused for a second lookup in the same scope, reassign index rather than introducing a new variable.
-int firstSlashIndex = path.indexOf('/', 1);
-int secondSlashIndex = path.indexOf('/', firstSlashIndex + 1);
+int index = path.indexOf('/', 1);
+index = path.indexOf('/', index + 1);
Why: Naming the loop variable entry and the extracted parts after the data they hold (typically key/name and value) keeps every map iteration readable in the same shape, regardless of the surrounding domain.
Examples:
-for (Map.Entry<String, Object> argumentEntry : arguments.entrySet()) {
- String paramName = argumentEntry.getKey();
- Object paramValue = argumentEntry.getValue();
+for (Map.Entry<String, Object> entry : arguments.entrySet()) {
+ String name = entry.getKey();
+ Object value = entry.getValue();
Why: Phrasing the predicate clause of a test method as <property>Is<state> rather than <subject>Has<state><property> makes a sorted method list group together by the property under test, and reads as a complete subject-verb-complement sentence.
Examples:
-public void testGetFooWhenBarHasNullBaz() throws Exception {
+public void testGetFooWhenBarBazIsNull() throws Exception {
-public void testGetFooWhenBarHasValidBaz() throws Exception {
+public void testGetFooWhenBarBazIsValid() throws Exception {
Why: A subsequent assertion that calls a method on the same reference would already throw a NullPointerException if the value were null, so the explicit nonnull check adds noise without adding coverage.
Examples:
Foo foo = service.findFoo();
-Assert.assertNotNull(foo);
Assert.assertEquals("expected", foo.getName());
Assert.assertEquals(1L, foo.getId());
Why: A local that is computed once and immediately handed to a single call site adds a name without adding meaning, so passing the expression directly removes a hop the reader otherwise has to follow.
Examples:
-Foo foo = makeFoo(arg);
-
-bar.consume(foo);
+bar.consume(makeFoo(arg));
-FooSchema fooSchema = computeSchema(args, root);
-
return Bar.builder(
).name(
"x"
).inputSchema(
- fooSchema
+ computeSchema(args, root)
).build();
Why: A verbose explanatory message on Assert.assertTrue or Assert.assertFalse mostly restates what the predicate already shows; removing it lets the failing line and stack frame carry the diagnostic, and shortens the test.
Examples:
-Assert.assertTrue(
- StringBundler.concat(
- "Lookup must use the entity's ", id,
- ". Actual filter was: ", filterString),
- filterString.contains("(id=" + id + ")"));
+Assert.assertTrue(filterString.contains("(id=" + id + ")"));
Why: Declaring a local right before the statement that consumes it keeps related lines together and removes the need to scan back to a top-of-method block to recall what each value means.
Examples:
-long alpha = randomLong();
-String beta = "https://example.com";
-String gamma = randomString();
-
Foo foo = Mockito.mock(Foo.class);
+long alpha = randomLong();
+
Mockito.when(
foo.getAlpha()
).thenReturn(
alpha
);
+String beta = "https://example.com";
+
Mockito.when(
foo.getBeta()
).thenReturn(
beta
);
Why: Calling .longValue(), .intValue(), or similar on the actual value forces a chain on the line being asserted; matching the boxed type on the expected side keeps the comparison readable on a single call.
Examples:
-Assert.assertEquals(
- 0L,
- threadLocal.getValue(
- ).longValue());
+Assert.assertEquals(Long.valueOf(0), threadLocal.getValue());
Why: When a local is declared and then immediately patched if its initial value is null or otherwise unsuitable, keeping the if directly after the declaration treats the pair as one logical "compute alpha" step and avoids splitting it across an unrelated declaration block.
Examples:
String alpha = source.getAlpha();
+
+if (alpha == null) {
+ alpha = fallback.getAlpha();
+}
+
String beta = null;
String gamma = null;
Date delta = source.getDelta();
-
-if (alpha == null) {
- alpha = fallback.getAlpha();
-}
Why: When the same object is configured by a contiguous block of setter calls, ordering the calls alphabetically by method name (and then by argument) makes the configuration easier to scan and matches the convention used for assertions and declarations.
Examples:
Foo foo = new Foo();
-foo.setGamma(gamma);
foo.setAlpha(alpha);
foo.setBeta(beta);
+foo.setGamma(gamma);
Why: Status, error, and notification strings that omit the linking verb read as fragments and translate poorly; restoring the auxiliary (is, are, was, were) turns the message into a complete sentence and matches the dominant phrasing already used across language files, log statements, and shell echoes.
Examples:
The rule applies to language property values.
-foo-not-allowed=Foo not allowed.
+foo-is-not-allowed=Foo is not allowed.
It applies to shell script messages.
- _log "Resource ${name} created successfully."
+ _log "Resource ${name} was created successfully."
It applies to workflow and other YAML scripted output.
- echo "No entries found for ${id}."
+ echo "No entries were found for ${id}."
Why: Liferay's persistence APIs spell entity destruction as delete* (deleteUser, deleteEntry); naming a private helper _delete* when its body calls a delete* service keeps the helper's verb aligned with the operation it performs.
Examples:
-private void _removeStaleFoos(Map<Long, List<String>> deletedIdsMap)
+private void _deleteStaleFoos(Map<Long, List<String>> deletedIdsMap)
throws Exception {
...
_fooLocalService.deleteFoo(foo);
}
Update the call sites at the same time.
-_removeStaleFoos(deletedIdsMap);
+_deleteStaleFoos(deletedIdsMap);