Skip to content

Commit

Permalink
Add an initial annotations artifact (with sample @Initializer impleme…
Browse files Browse the repository at this point in the history
…ntation) (#709)

The main purpose of this change is to introduce our own annotations artifact, which
can be leveraged to implement more general contracts and other annotations of
interest to NullAway.

Additionally, we start by having our own `@Initializer` annotation "implementation"
in this annotations jar. I believe Facebook/Meta's Eradicate is being sunset in favor of
Nullsafe (internally at Meta) and NullAway (for OSS), and either way recommending 
their annotation jar for NullAway is more of a historical artifact of nullness checking at 
Uber and our previous use of Infer/Eradicate than anything else. NullAway will still
acknowledge any annotation with simple name `@Initializer`, but now we can
recommend a canonical alternative which we can make sure remains supported.

Additionally, we take the opportunity to make our `@Initializer` valid only on method
declarations (which is the only place NullAway checks for it).

We use `annotations` rather than `annotation`, because that's the choice JSpecify
0.3.0 went with in the end, and I refuse to spend another year discussing that 😉
  • Loading branch information
lazaroclapp authored Jan 5, 2023
1 parent 3ad8876 commit afb8fd4
Show file tree
Hide file tree
Showing 12 changed files with 128 additions and 8 deletions.
51 changes: 51 additions & 0 deletions annotations/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2017. Uber Technologies
*
* 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.
*/
import net.ltgt.gradle.errorprone.CheckSeverity

plugins {
id 'java-library'
id 'nullaway.jacoco-conventions'
}

sourceCompatibility = 1.8

dependencies {
}

test {
maxHeapSize = "1024m"
if (!JavaVersion.current().java9Compatible) {
jvmArgs "-Xbootclasspath/p:${configurations.errorproneJavac.asPath}"
} else {
// to expose necessary JDK types on JDK 16+; see https://errorprone.info/docs/installation#java-9-and-newer
jvmArgs += [
"--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED",
"--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED",
"--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED",
"--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED",
"--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED",
"--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED",
"--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
"--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
"--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
"--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED",
// Accessed by Lombok tests
"--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED",
]
}
}

apply plugin: 'com.vanniktech.maven.publish'
19 changes: 19 additions & 0 deletions annotations/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#
# Copyright (C) 2017. Uber Technologies
#
# 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.
#

POM_NAME=NullAway
POM_ARTIFACT_ID=nullaway-annotations
POM_PACKAGING=jar
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2023 Uber Technologies, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package com.uber.nullaway.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* An annotation used to mark a method as an initializer.
*
* <p>During initialization checking (see <a
* href=/~https://github.com/uber/NullAway/wiki/Error-Messages#initializer-method-does-not-guarantee-nonnull-field-is-initialized--nonnull-field--not-initialized>NullAway
* Wiki</a>), NullAway considers a method marked with any annotation with simple name
* {@code @Initializer} to denote an initializer method. Initializer methods are assumed by NullAway
* to always be called before any other method of the class that is not a constructor or called from
* a constructor. This means a non-null field is considered to be properly initialized if it's set
* by such an initializer method. By design, NullAway doesn't check for such initialization, since
* an important use case of initializer methods is documenting methods used by annotation processors
* or external frameworks as part of object set up (e.g. {@code android.app.Activity.onCreate} or
* {@code javax.annotation.processing.Processor.init}). Note that there are other ways of defining
* initializer methods from external libraries (i.e. library models), and that a method overriding
* an initializer method is always considered an initializer method (again, for the sake of
* framework events such as {@code onCreate}).
*/
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.METHOD})
public @interface Initializer {}
1 change: 1 addition & 0 deletions code-coverage-report/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ coverallsTask.configure {
// when computing overall coverage. We aim to measure coverage for all code that actually ships
// in a Maven artifact (so, e.g., we do not measure coverage for the jmh module)
dependencies {
implementation project(':annotations')
implementation project(':nullaway')
implementation project(':jar-infer:jar-infer-lib')
implementation project(':jar-infer:nullaway-integration-test')
Expand Down
1 change: 0 additions & 1 deletion gradle/dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ def test = [
junit4 : "junit:junit:4.13.2",
junit5Jupiter : ["org.junit.jupiter:junit-jupiter-api:5.0.2","org.apiguardian:apiguardian-api:1.0.0"],
jetbrainsAnnotations : "org.jetbrains:annotations:13.0",
inferAnnotations : "com.facebook.infer.annotation:infer-annotation:0.11.0",
cfQual : "org.checkerframework:checker-qual:${versions.checkerFramework}",
// 2.5.5 is the last release to contain this artifact
cfCompatQual : "org.checkerframework:checker-compat-qual:2.5.5",
Expand Down
4 changes: 2 additions & 2 deletions nullaway/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ configurations {
}

dependencies {
compileOnly project(":annotations")
compileOnly deps.apt.autoValueAnnot
annotationProcessor deps.apt.autoValue
compileOnly deps.apt.autoServiceAnnot
annotationProcessor deps.apt.autoService
compileOnly deps.test.inferAnnotations
compileOnly deps.build.jsr305Annotations
compileOnly deps.test.jetbrainsAnnotations

Expand All @@ -38,6 +38,7 @@ dependencies {
implementation deps.build.checkerDataflow
implementation deps.build.guava

testImplementation project(":annotations")
testImplementation deps.test.junit4
testImplementation(deps.build.errorProneTestHelpers) {
exclude group: "junit", module: "junit"
Expand All @@ -48,7 +49,6 @@ dependencies {
testImplementation deps.test.cfCompatQual
testImplementation deps.build.jspecify
testImplementation project(":test-java-lib")
testImplementation deps.test.inferAnnotations
testImplementation deps.apt.jakartaInject
testImplementation deps.apt.javaxInject
testImplementation deps.test.rxjava2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@
* THE SOFTWARE.
*/

import com.facebook.infer.annotation.Initializer;
import com.google.errorprone.util.ASTHelpers;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.util.Name;
import com.uber.nullaway.annotations.Initializer;
import org.checkerframework.nullaway.dataflow.cfg.node.MethodInvocationNode;
import org.checkerframework.nullaway.dataflow.cfg.node.Node;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@

package com.uber.nullaway.testdata;

import com.facebook.infer.annotation.Initializer;
import com.google.errorprone.annotations.concurrent.LazyInit;
import com.uber.nullaway.annotations.Initializer;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.junit.Before;
import org.junit.BeforeClass;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

package com.uber.nullaway.testdata;

import com.facebook.infer.annotation.Initializer;
import com.uber.nullaway.annotations.Initializer;
import javax.annotation.Nullable;

/** Created by msridhar on 3/7/17. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

import static com.uber.nullaway.testdata.Util.castToNonNull;

import com.facebook.infer.annotation.Initializer;
import com.uber.nullaway.annotations.Initializer;
import javax.annotation.Nullable;

public class ReadBeforeInitNegativeCases {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

package com.uber.nullaway.testdata;

import com.facebook.infer.annotation.Initializer;
import com.uber.nullaway.annotations.Initializer;

public class ReadBeforeInitPositiveCases {

Expand Down
1 change: 1 addition & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pluginManagement {
}
}

include ':annotations'
include ':nullaway'
include ':sample-library-model'
include ':sample'
Expand Down

0 comments on commit afb8fd4

Please sign in to comment.