Coding Standards & Style Guide
August 6, 2026 · View on GitHub
1. Code Formatting — Checkstyle
The project uses Checkstyle 8.25 with a custom rule set based on the
Google Java Style Guide.
The configuration lives at checkstyle.xml in the project root.
Checkstyle runs automatically at the verify phase:
mvn checkstyle:check # check only (fast)
mvn verify -DskipTests # full verify phase including Checkstyle
Violations at warning severity fail the build (<failOnViolation>true</failOnViolation>).
Key Checkstyle Rules
| Rule | Requirement |
|---|---|
| Copyright header | Every .java, .properties, and .xml file must contain a copyright header with a valid Apache 2.0 license reference |
| No tab characters | Use spaces throughout; tabs anywhere in the file fail the build |
OneTopLevelClass | Each Java file must contain exactly one top-level type |
NoLineWrap | Import statements must not be line-wrapped |
NeedBraces | All if, else, for, while, do bodies must have braces |
LeftCurly | Opening brace on a new line (nl option) |
RightCurly | Closing brace on its own line (alone option) |
OneStatementPerLine | One statement per line |
MultipleVariableDeclarations | Declare each variable on its own line |
EmptyBlock | Empty blocks must contain text (a comment), not be truly empty |
EmptyCatchBlock | Allowed only when the exception variable is named expected or ignored |
FallThrough | Switch fall-through must have a comment |
ModifierOrder | Modifiers in the order: public protected private abstract default static final transient volatile synchronized native strictfp |
Naming Conventions (Enforced by Checkstyle)
| Element | Pattern | Example |
|---|---|---|
| Package | [a-zA-Z]+(\.[_a-zA-Z][_a-zA-Z0-9]*)* | org.finos.legend.pure.m3 |
| Class / Interface / Enum | [_a-zA-Z][_a-zA-Z0-9]* | CoreInstance, M3Compiler |
| Method | [_a-zA-Z][a-zA-Z0-9_$]* | getValueForMetaPropertyToOne |
| Member variable | [_a-zA-Z][_a-zA-Z0-9]* | sourceInformation, _name |
| Parameter | [_a-zA-Z][_a-zA-Z0-9]*? | propertyName, instance |
| Local variable | [_a-zA-Z][_a-zA-Z0-9]*? | result, currentNode |
| Type parameter | (^[A-Z][0-9]?)|([A-Z][a-zA-Z0-9]*) | T, V, CoreType |
The patterns are intentionally permissive compared to strict Google style (they allow underscores and capital-first members) to accommodate the Legacy codebase.
Import Order
CustomImportOrder is enabled with separateLineBetweenGroups=true. IntelliJ can
be configured to match: Settings → Editor → Code Style → Java → Imports →
"Use single class imports", layout per Google style.
2. Copyright Header Template
Every new file must start with comment similar to the below:
// Copyright <YEAR> Goldman Sachs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
For XML and properties files the comment style must be adapted accordingly.
Checkstyle validates the presence of Copyright and the Apache license URL
via RegexpMultiline.
3. General Code Conventions
Collections
- Prefer Eclipse Collections over
java.utilcollections for all new code. - Use
Lists.mutable.empty()/Lists.immutable.with(...)instead ofnew ArrayList<>()/List.of(...). - Return
RichIterableorListIterablefrom APIs, notjava.util.List, unless you needjava.utilcompatibility.
Null Handling
- Avoid returning
nullfrom public methods. UseOptional(sparingly) or throw a meaningful exception. - Eclipse Collections methods like
getIfAbsent,getIfAbsentPut, anddetectremove common null-check patterns.
Method Visibility
- Make methods as package-private as possible for testability without exposing them as public API.
- When widening visibility for testing, add a comment:
// visible for testing(do not add a Guava@VisibleForTestingannotation dependency solely for this).
Logging
// Correct
private static final Logger LOGGER = LoggerFactory.getLogger(MyClass.class);
LOGGER.info("Compiling repository: {}", repositoryName);
// Wrong — uses raw System.out or System.err
System.out.println("Compiling...");
- Use
{}placeholders instead of string concatenation in log calls. - Log level guidelines:
TRACE— very detailed, loop-level diagnostics (disabled in production).DEBUG— developer diagnostics; individual step outcomes.INFO— major milestones (start/end of compilation, plugin execution).WARN— unexpected but recoverable state; deprecated API usage.ERROR— unrecoverable failures; exceptions that propagate to the user.
- Never log credentials, personal data, raw SQL with user values, or security tokens.
Exception Handling
// Correct — named 'expected' or 'ignored'
try {
parseOptionalElement();
}
catch (Exception expected)
{
// intentionally ignored: element is optional
}
// Wrong — empty catch without a name or comment
try { ... } catch (Exception e) {}
- Do not swallow
PureCompilationExceptionorPureExecutionExceptionwithout re-throwing or explicitly logging. - Do not call
System.exit()anywhere in library code. - Prefer specific exception types over catching
ExceptionorThrowable.
4. Git Workflow & Branching Strategy
The project follows a feature-branch / GitHub Flow model:
main (master)
└── feature/<short-description>
└── fix/<short-description>
└── docs/<short-description>
Branch Naming
| Prefix | Purpose |
|---|---|
feature/ | New functionality |
fix/ | Bug fixes |
docs/ | Documentation-only changes |
refactor/ | Internal restructuring without behaviour change |
test/ | Test additions or corrections |
chore/ | Dependency upgrades, build configuration |
Commit Message Convention
<type>(<scope>): <short summary in present tense, ≤72 chars>
[Optional longer body explaining WHY, not WHAT]
[Optional: Closes #<issue-number>]
Types: feat, fix, docs, test, refactor, chore, perf
Example:
feat(compiler): add write-if-changed guard to PureCompilerBinaryGenerator
Prevents downstream Maven plugins from re-compiling unchanged generated files,
significantly improving incremental build times.
Closes #1234
5. Pull Request Checklist
Before opening a PR, verify every item:
-
mvn installpasses locally (no test failures, no Checkstyle violations). - All new Java files have the copyright header.
- New or changed behaviour has tests (see Testing Strategy).
- No new
System.out.printlnore.printStackTrace()calls. - No new
nullreturns from public methods without documentation. - Dependency changes in
pom.xmluse the managed version from the root POM. - If a module's behaviour changed, the module's
README.mdis updated. - If a new library was added, the Technology Stack doc is updated.
- PR description explains what changed and why.
- PR is linked to the relevant GitHub issue (if any).
Code Review Expectations
- Reviewers should check: correctness, test coverage, style compliance, and impact on the downstream Legend platform.
- Authors should respond to all review comments before merging.
- At least one approving review is required before merging to
master. - Do not merge your own PR unless it is a trivial documentation fix.
6. API Design Conventions
Legend Pure is a library, not a web service. There are no REST endpoints in this repository. API conventions apply to Java public APIs:
- Method naming:
getX()for simple accessors,findX()for nullable lookups,resolveX()for operations that compute a result,buildX()for factory/builder patterns. - Immutability: Prefer returning
ImmutableList/ImmutableSetfrom public APIs to prevent callers from mutating internal state. - Backwards compatibility: Public interfaces and classes in
legend-pure-m4andlegend-pure-m3-coreare consumed by downstream Legend projects. Adding methods to interfaces is a breaking change unless a default implementation is provided. - Deprecation: Annotate with
@Deprecatedand add a Javadoc@deprecatedtag explaining the replacement. Do not remove deprecated methods in the same release that deprecates them.
Documentation in Pure source
Prose on <<PCT.function>> declarations and <<PCT.test>> cases is published to end users and has its
own standard: PCT Function Documentation. Documentation is a '''…''' literal
placed before the declaration, not a comment — see
Pure Language Reference § Documentation for the
mechanics.
Two things to note: an element may not carry both documentation and an explicit {doc.doc=…} tagged
value, and adding documentation shifts the lines below it, which breaks the position assertions some
platform tests make. The standard lists the affected files.
Back: Build & CI Guide · Next: Testing Strategy