# Checker Framework developer manual

If you wish to use the Checker Framework, see its user manual (HTML, PDF).

This document contains information for Checker Framework developers, including people who wish to edit its source code or make pull requests.

Contents:

- Directory structure
- Build tasks
- Testing the Checker Framework
- Code style
- IDE configuration
  - Configure Eclipse to edit the Checker Framework
- Pull requests
  - Pull request and commit notes for maintainers
- Continuous Integration
  - What to do if a Continuous Integration build fails
- Testing optimizations
- Documenting refactoring ideas
- Version numbers for annotated libraries
- Making a Checker Framework release

## Directory structure

The checker-framework repository contains several related projects:

`framework`
  the framework that enables building pluggable type checkers
`checker`
  the type checkers provided with the Checker Framework
`javacutil`
  utilities for integrating with javac
`dataflow`
  a dataflow framework that is used by the Checker Framework, Error Prone, NullAway, and other tools

The repository also contains the following directories:

`docs`
  documentation: manual, tutorial, examples, developer docs
`maven-artifacts`
  artifacts to be uploaded to Maven Central

## Build tasks

Full instructions for building the Checker Framework from sources appear in the Checker Framework manual. This section describes the build system (the Gradle build tasks).

Don't run the `gradle` command, which would use whatever version of Gradle is installed on your computer. Instead, use the `gradlew` script in the `checker-framework` directory, also known as the Gradle wrapper.

Frequently-used tasks:

- `assemble`: builds all jars except `jdk8.jar`, including javadoc jars and fat jars that contain all dependencies.
- `build`: `assemble`, plus runs all JUnit tests.
- `buildJdk`: builds `jdk8.jar`.
- `allTests`: runs all tests.
- `reformat`: reformats Java files.
- `NameOfJUnitTest`: runs the JUnit test with that name; for example, `NullnessFbcTest`.
- `task`: lists tasks; use `--all` to see all tasks.

If you run a task from the main directory, then it will run that task in all subprojects with a task by that name. So, if you run `./gradlew allTests` that runs all tests everywhere. But `(cd framework && ../gradlew allTests)` only runs tests in the `framework` project. Alternatively, running `:framework:allTests` from the main directory or any subproject runs the `allTests` task only in the `framework` project.

## Testing the Checker Framework

For writing new test cases, see file [`checker/tests/README`](https://raw.githubusercontent.com/typetools/checker-framework/master/checker/tests/README).

## Code style

Code in this project follows the Google Java Style Guide (except 4 spaces are used for indentation), Michael Ernst's coding style guidelines, and Oracle's Java code conventions.

From the command line, you can format your code by running `./gradlew reformat`. You can configure your IDE (Eclipse or IntelliJ) to use the formatting (don't forget the non-standard `-a` flag).

We don't use `@author` Javadoc tags in code files. Doing so clutters the code, and is misleading once that individual is no longer maintaining the code. Authorship (and who has made changes recently) can be obtained from the version control system, such as by running `git annotate filename`.

Every class, method, and field (even private ones) must have a descriptive Javadoc comment.

## IDE configuration

### Configure Eclipse to edit the Checker Framework

These instructions are relevant if you use Eclipse as your IDE.

1. Clone and build all projects from their sources.
2. Download Eclipse from the official Eclipse website and install it.
3. Run Eclipse.
4. Enter the main Eclipse working screen and in the “File” menu, select “Import” ⇒ “General” ⇒ “Existing Projects into Workspace”.
5. After the “Import Projects” window appears, select “Select Root Directory”, and select the parent of the `$CHECKERFRAMEWORK` directory.
6. Ensure “Search for nested projects” is selected in the Options panel.
7. Select all the projects in the folder except for “personalblog-demo”, then select “Finish” to import the projects.

Eclipse should successfully build all the imported projects. If Eclipse reports any errors, ensure you followed the instructions for cloning and building all projects.

## Pull requests

Each pull request should address a single concern, rather than (say) addressing multiple concerns such as fixing a bug, adding a feature, and changing formatting. Focusing each pull request on a single concern makes the commit easier to understand and review. It also makes the commit history (after the pull request is merged) easier to understand and (if necessary) revert.

The pull request title should clearly explain the change. It will be used as the commit message for your change. If the pull request fixes an issue in the issue tracker, its title should end with "; fixes #NNN" where NNN is the fixed issue.

Your pull request (whether it is a bug fix or a new feature) should include tests that fail before your change and pass afterward.

If you make a user-visible change, update the manual (or add a new section) and add a brief description at the top of the changelog (file `changelog.txt`).

To reduce iterations of code review, please follow the coding conventions. Also enable continuous integration on your fork of the Checker Framework and ensure that it passes before you open a pull request.

It is good style to create a branch (in your fork of the Checker Framework GitHub repository) for each independent change. Do not make changes to your `master` branch.

If you make related changes in the `checker-framework` and `checker-framework-inference` repositories, use the same branch name for each. The continuous integration framework will find and use that branch when running tests.

Also see Michael Ernst's advice about creating GitHub pull requests.

### Pull request and commit notes for maintainers

It is acceptable to commit small, noncontroversial changes directly to master. (This policy differs from some projects, which require an issue tracker issue and a pull request for every change, however minor.) As with pull requests, each commit should address a single concern. For any change where you want feedback, or where others might have useful comments or might disagree, please submit a pull request. Be conservative in your judgment; others might consider something controversial that you do not.

Try to review pull requests promptly, to avoid stalling others while waiting for your feedback. If you have been waiting for more than a week after the pull request was assigned with no feedback, then ping the assignee, wait at least another business day, and then go ahead and push your changes. It's great if reviewers can give feedback, but if they are too busy to do so, you should recognize that and move on.

## Continuous Integration

The Checker Framework has continuous integration jobs that run in Azure Pipelines, CircleCI, and/or Travis CI on each push to GitHub.

To enable Travis CI continuous integration for your fork:

- Browse to travis-ci.com
- Click the downarrow for the dropdown, near your face in the upper right corner
- Click settings
- Find "checker-framework" in the list, and click the slider to enable it.

To enable Azure Pipelines continuous integration for your fork:

- Go to dev.azure.com. (You might need to create a (free) account.)
- Click "Create a project to get started"
- Click "public".
- Click "create project"
- At the left, click the blue rocket labeled "pipelines"
- Click "new pipeline"
- Click "GitHub" (You might need to authorize the app on GitHub.)
- Click "Select a repository"
- Choose MYUSERID/checker-framework
- Choose the default radio button, "only selected repositories". Do not choose "all repositories".
- Approve and install.
- Click "run".

### What to do if a Continuous Integration build fails

Sometimes, CI tests for your pull request may fail even though your local build passed. This is usually because the CI service performed more tests than you ran locally.

First, examine the CI service's logs, which contain diagnostic output from the failing command. You can determine which command was run from the logs, or from the CI configuration file (such as `azure-pipelines.yml`).

## Testing optimizations

To test an optimization that should speed up type-checking, see the `test-daikon.sh` stage of the `daikon_jdk8` job of the Azure Pipelines CI job. Compare the run time of this stage (or of the entire `daikon_jdk8` job) between the master branch and a branch with your improvements.

You can also compare run times of the Checker Framework test suite.

## Documenting refactoring ideas

If you have an idea for a code improvement (such as a refactoring), please document it. If it can be described concisely and is low priority, a TODO comment in the code is more appropriate than an enhancement request in the issue tracker. The code comment is more likely to be noticed by someone working with the code, and it is equally easy to search for. Furthermore, it doesn't clutter the issue tracker. Clutter in the issue tracker reduces morale, makes it harder to search, and makes the project appear lower-quality than it actually is.

## Version numbers for annotated libraries

We maintain annotated versions of some third-party libraries. The source code appears in a fork in the GitHub `typetools` organization. Binaries are hosted at Maven Central in the `org.checkerframework.annotatedlib` group.

Annotated libraries should be based on a released version of the upstream library, not an arbitrary commit in the upstream library's version control system. The library's version number is the same as the upstream version number.

When making a new version of an annotated library, between upstream releases, add ".0.1" to the end of the version number. For example, if we already uploaded version 6.2 to Maven Central, the next version we upload would be 6.2.0.1. This accommodates the possibility that the upstream maintainers release 6.2.1. Our further releases increment the last number, for example to 6.2.0.2.

## Making a Checker Framework release

See a separate document about the Checker Framework release process.