diff --git a/compiler/testData/foreignAnnotations/annotations/android/support/annotation/NonNull.java b/compiler/testData/foreignAnnotations/annotations/android/support/annotation/NonNull.java
new file mode 100644
index 00000000000..5a7c86d063d
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/annotations/android/support/annotation/NonNull.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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.
+ */
+package android.support.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+/**
+ * Denotes that a parameter, field or method return value can never be null.
+ *
+ * This is a marker annotation and it has no specific attributes.
+ */
+@Retention(CLASS)
+@Target({METHOD, PARAMETER, FIELD})
+public @interface NonNull {
+}
diff --git a/compiler/testData/foreignAnnotations/annotations/android/support/annotation/Nullable.java b/compiler/testData/foreignAnnotations/annotations/android/support/annotation/Nullable.java
new file mode 100644
index 00000000000..c427b649ce6
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/annotations/android/support/annotation/Nullable.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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.
+ */
+package android.support.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+/**
+ * Denotes that a parameter, field or method return value can be null.
+ *
+ * When decorating a method call parameter, this denotes that the parameter can
+ * legitimately be null and the method will gracefully deal with it. Typically
+ * used on optional parameters.
+ *
+ * When decorating a method, this denotes the method might legitimately return
+ * null.
+ *
+ * This is a marker annotation and it has no specific attributes.
+ */
+@Retention(CLASS)
+@Target({METHOD, PARAMETER, FIELD})
+public @interface Nullable {
+}
diff --git a/compiler/testData/foreignAnnotations/annotations/edu/umd/cs/findbugs/annotations/CheckForNull.java b/compiler/testData/foreignAnnotations/annotations/edu/umd/cs/findbugs/annotations/CheckForNull.java
new file mode 100644
index 00000000000..1d637f2b3ce
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/annotations/edu/umd/cs/findbugs/annotations/CheckForNull.java
@@ -0,0 +1,47 @@
+/*
+ * Bytecode Analysis Framework
+ * Copyright (C) 2005 University of Maryland
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package edu.umd.cs.findbugs.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.annotation.meta.TypeQualifierNickname;
+import javax.annotation.meta.When;
+
+/**
+ * The annotated element might be null, and uses of the element should check for
+ * null.
+ *
+ * When this annotation is applied to a method it applies to the method return
+ * value.
+ *
+ * @deprecated - use {@link javax.annotation.CheckForNull} instead.
+ **/
+@Documented
+@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE })
+@Retention(RetentionPolicy.CLASS)
+@javax.annotation.Nonnull(when = When.MAYBE)
+@TypeQualifierNickname
+@Deprecated
+public @interface CheckForNull {
+
+}
diff --git a/compiler/testData/foreignAnnotations/annotations/edu/umd/cs/findbugs/annotations/NonNull.java b/compiler/testData/foreignAnnotations/annotations/edu/umd/cs/findbugs/annotations/NonNull.java
new file mode 100644
index 00000000000..c73309e4fa2
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/annotations/edu/umd/cs/findbugs/annotations/NonNull.java
@@ -0,0 +1,46 @@
+/*
+ * Bytecode Analysis Framework
+ * Copyright (C) 2005 University of Maryland
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package edu.umd.cs.findbugs.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.annotation.meta.TypeQualifierNickname;
+import javax.annotation.meta.When;
+
+/**
+ * The annotated element must not be null.
+ *
+ * Annotated Fields must only not be null after construction has completed.
+ * Annotated methods must have non-null return values.
+ *
+ * @deprecated - use {@link javax.annotation.Nonnull} instead.
+ **/
+@Documented
+@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE })
+@Retention(RetentionPolicy.CLASS)
+@javax.annotation.Nonnull(when = When.ALWAYS)
+@TypeQualifierNickname
+@Deprecated
+public @interface NonNull {
+
+}
diff --git a/compiler/testData/foreignAnnotations/annotations/edu/umd/cs/findbugs/annotations/Nullable.java b/compiler/testData/foreignAnnotations/annotations/edu/umd/cs/findbugs/annotations/Nullable.java
new file mode 100644
index 00000000000..41e97d57d08
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/annotations/edu/umd/cs/findbugs/annotations/Nullable.java
@@ -0,0 +1,50 @@
+/*
+ * Bytecode Analysis Framework
+ * Copyright (C) 2005 University of Maryland
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package edu.umd.cs.findbugs.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.annotation.meta.TypeQualifierNickname;
+import javax.annotation.meta.When;
+
+/**
+ * The annotated element could be null under some circumstances.
+ *
+ * In general, this means developers will have to read the documentation to
+ * determine when a null value is acceptable and whether it is necessary to
+ * check for a null value.
+ *
+ * When this annotation is applied to a method it applies to the method return
+ * value.
+ *
+ * @deprecated - use {@link javax.annotation.Nullable} instead.
+ **/
+@Documented
+@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE })
+@Retention(RetentionPolicy.CLASS)
+@javax.annotation.Nonnull(when = When.UNKNOWN)
+@TypeQualifierNickname
+@Deprecated
+public @interface Nullable {
+
+}
diff --git a/compiler/testData/foreignAnnotations/annotations/edu/umd/cs/findbugs/annotations/PossiblyNull.java b/compiler/testData/foreignAnnotations/annotations/edu/umd/cs/findbugs/annotations/PossiblyNull.java
new file mode 100644
index 00000000000..e0346cda130
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/annotations/edu/umd/cs/findbugs/annotations/PossiblyNull.java
@@ -0,0 +1,49 @@
+/*
+ * Bytecode Analysis Framework
+ * Copyright (C) 2005 University of Maryland
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package edu.umd.cs.findbugs.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.annotation.meta.TypeQualifierNickname;
+import javax.annotation.meta.When;
+
+/**
+ * The annotated element should might be null, and uses of the element should
+ * check for null.
+ *
+ * When this annotation is applied to a method it applies to the method return
+ * value.
+ *
+ * @deprecated - use CheckForNull instead; the name of which more clearly
+ * indicates that not only could the value be null, but that good
+ * coding practice requires that the value be checked for null.
+ **/
+@Documented
+@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE })
+@Retention(RetentionPolicy.CLASS)
+@javax.annotation.Nonnull(when = When.MAYBE)
+@TypeQualifierNickname
+@Deprecated
+public @interface PossiblyNull {
+
+}
diff --git a/compiler/testData/foreignAnnotations/annotations/edu/umd/cs/findbugs/annotations/UnknownNullness.java b/compiler/testData/foreignAnnotations/annotations/edu/umd/cs/findbugs/annotations/UnknownNullness.java
new file mode 100644
index 00000000000..06c01523daf
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/annotations/edu/umd/cs/findbugs/annotations/UnknownNullness.java
@@ -0,0 +1,42 @@
+/*
+ * Bytecode Analysis Framework
+ * Copyright (C) 2005-2006 University of Maryland
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package edu.umd.cs.findbugs.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.annotation.meta.TypeQualifierNickname;
+import javax.annotation.meta.When;
+
+/**
+ * Used to indicate that the nullness of element is unknown, or may vary in
+ * unknown ways in subclasses.
+ **/
+@Documented
+@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE })
+@Retention(RetentionPolicy.CLASS)
+@javax.annotation.Nonnull(when = When.UNKNOWN)
+@TypeQualifierNickname
+@Deprecated
+public @interface UnknownNullness {
+
+}
diff --git a/compiler/testData/foreignAnnotations/annotations/javax/annotation/CheckForNull.java b/compiler/testData/foreignAnnotations/annotations/javax/annotation/CheckForNull.java
new file mode 100644
index 00000000000..6fe52005c26
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/annotations/javax/annotation/CheckForNull.java
@@ -0,0 +1,16 @@
+package javax.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import javax.annotation.meta.TypeQualifierNickname;
+import javax.annotation.meta.When;
+
+@Documented
+@TypeQualifierNickname
+@Nonnull(when = When.MAYBE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface CheckForNull {
+
+}
diff --git a/compiler/testData/foreignAnnotations/annotations/javax/annotation/Nonnull.java b/compiler/testData/foreignAnnotations/annotations/javax/annotation/Nonnull.java
new file mode 100644
index 00000000000..4b7aad97c70
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/annotations/javax/annotation/Nonnull.java
@@ -0,0 +1,26 @@
+package javax.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import javax.annotation.meta.TypeQualifier;
+import javax.annotation.meta.TypeQualifierValidator;
+import javax.annotation.meta.When;
+
+@Documented
+@TypeQualifier
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Nonnull {
+ When when() default When.ALWAYS;
+
+ static class Checker implements TypeQualifierValidator {
+
+ public When forConstantValue(Nonnull qualifierqualifierArgument,
+ Object value) {
+ if (value == null)
+ return When.NEVER;
+ return When.ALWAYS;
+ }
+ }
+}
diff --git a/compiler/testData/foreignAnnotations/annotations/javax/annotation/Nullable.java b/compiler/testData/foreignAnnotations/annotations/javax/annotation/Nullable.java
new file mode 100644
index 00000000000..d31993dbd77
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/annotations/javax/annotation/Nullable.java
@@ -0,0 +1,16 @@
+package javax.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import javax.annotation.meta.TypeQualifierNickname;
+import javax.annotation.meta.When;
+
+@Documented
+@TypeQualifierNickname
+@Nonnull(when = When.UNKNOWN)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Nullable {
+
+}
diff --git a/compiler/testData/foreignAnnotations/annotations/javax/annotation/meta/TypeQualifier.java b/compiler/testData/foreignAnnotations/annotations/javax/annotation/meta/TypeQualifier.java
new file mode 100644
index 00000000000..99f63127277
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/annotations/javax/annotation/meta/TypeQualifier.java
@@ -0,0 +1,27 @@
+package javax.annotation.meta;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This qualifier is applied to an annotation to denote that the annotation
+ * should be treated as a type qualifier.
+ */
+
+@Documented
+@Target(ElementType.ANNOTATION_TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface TypeQualifier {
+
+ /**
+ * Describes the kinds of values the qualifier can be applied to. If a
+ * numeric class is provided (e.g., Number.class or Integer.class) then the
+ * annotation can also be applied to the corresponding primitive numeric
+ * types.
+ */
+ Class> applicableTo() default Object.class;
+
+}
diff --git a/compiler/testData/foreignAnnotations/annotations/javax/annotation/meta/TypeQualifierDefault.java b/compiler/testData/foreignAnnotations/annotations/javax/annotation/meta/TypeQualifierDefault.java
new file mode 100644
index 00000000000..0c8bd528fc4
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/annotations/javax/annotation/meta/TypeQualifierDefault.java
@@ -0,0 +1,20 @@
+package javax.annotation.meta;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This qualifier is applied to an annotation to denote that the annotation
+ * defines a default type qualifier that is visible within the scope of the
+ * element it is applied to.
+ */
+
+@Documented
+@Target(ElementType.ANNOTATION_TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface TypeQualifierDefault {
+ ElementType[] value() default {};
+}
diff --git a/compiler/testData/foreignAnnotations/annotations/javax/annotation/meta/TypeQualifierNickname.java b/compiler/testData/foreignAnnotations/annotations/javax/annotation/meta/TypeQualifierNickname.java
new file mode 100644
index 00000000000..40c998382da
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/annotations/javax/annotation/meta/TypeQualifierNickname.java
@@ -0,0 +1,33 @@
+package javax.annotation.meta;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ *
+ * This annotation is applied to a annotation, and marks the annotation as being
+ * a qualifier nickname. Applying a nickname annotation X to a element Y should
+ * be interpreted as having the same meaning as applying all of annotations of X
+ * (other than QualifierNickname) to Y.
+ *
+ *
+ * Thus, you might define a qualifier SocialSecurityNumber as follows:
+ *
+ *
+ *
+ *
+ @Documented
+ @TypeQualifierNickname @Pattern("[0-9]{3}-[0-9]{2}-[0-9]{4}")
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface SocialSecurityNumber {
+ }
+
+ *
+ *
+ */
+@Documented
+@Target(ElementType.ANNOTATION_TYPE)
+public @interface TypeQualifierNickname {
+
+}
diff --git a/compiler/testData/foreignAnnotations/annotations/javax/annotation/meta/TypeQualifierValidator.java b/compiler/testData/foreignAnnotations/annotations/javax/annotation/meta/TypeQualifierValidator.java
new file mode 100644
index 00000000000..8053011296b
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/annotations/javax/annotation/meta/TypeQualifierValidator.java
@@ -0,0 +1,21 @@
+package javax.annotation.meta;
+
+import java.lang.annotation.Annotation;
+
+import javax.annotation.Nonnull;
+
+public interface TypeQualifierValidator {
+ /**
+ * Given a type qualifier, check to see if a known specific constant value
+ * is an instance of the set of values denoted by the qualifier.
+ *
+ * @param annotation
+ * the type qualifier
+ * @param value
+ * the value to check
+ * @return a value indicating whether or not the value is an member of the
+ * values denoted by the type qualifier
+ */
+ public @Nonnull
+ When forConstantValue(@Nonnull A annotation, Object value);
+}
diff --git a/compiler/testData/foreignAnnotations/annotations/javax/annotation/meta/When.java b/compiler/testData/foreignAnnotations/annotations/javax/annotation/meta/When.java
new file mode 100644
index 00000000000..ec8a1bc7037
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/annotations/javax/annotation/meta/When.java
@@ -0,0 +1,23 @@
+package javax.annotation.meta;
+
+/**
+ * Used to describe the relationship between a qualifier T and the set of values
+ * S possible on an annotated element.
+ *
+ * In particular, an issues should be reported if an ALWAYS or MAYBE value is
+ * used where a NEVER value is required, or if a NEVER or MAYBE value is used
+ * where an ALWAYS value is required.
+ *
+ *
+ */
+public enum When {
+ /** S is a subset of T */
+ ALWAYS,
+ /** nothing definitive is known about the relation between S and T */
+ UNKNOWN,
+ /** S intersection T is non empty and S - T is nonempty */
+ MAYBE,
+ /** S intersection T is empty */
+ NEVER;
+
+}
diff --git a/compiler/testData/foreignAnnotations/annotations/lombok/NonNull.java b/compiler/testData/foreignAnnotations/annotations/lombok/NonNull.java
new file mode 100644
index 00000000000..7a2f55a7070
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/annotations/lombok/NonNull.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009-2013 The Project Lombok Authors.
+ *
+ * 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 lombok;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * If put on a parameter, lombok will insert a null-check at the start of the method / constructor's body, throwing a
+ * {@code NullPointerException} with the parameter's name as message. If put on a field, any generated method assigning
+ * a value to this field will also produce these nullchecks.
+ *
+ * Note that any annotation named {@code NonNull} with any casing and any package will result in nullchecks produced for
+ * generated methods (and the annotation will be copied to the getter return type and any parameters of generated methods),
+ * but only this annotation, if present on a parameter, will result in a null check inserted into your otherwise
+ * handwritten method.
+ *
+ * WARNING: If the java community ever does decide on supporting a single {@code @NonNull} annotation (for example via JSR305), then
+ * this annotation will be deleted from the lombok package. If the need to update an import statement scares
+ * you, you should use your own annotation named {@code @NonNull} instead of this one.
+ */
+@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
+@Retention(RetentionPolicy.CLASS)
+@Documented
+public @interface NonNull {
+}
\ No newline at end of file
diff --git a/compiler/testData/foreignAnnotations/annotations/org/checkerframework/checker/nullness/qual/NonNull.java b/compiler/testData/foreignAnnotations/annotations/org/checkerframework/checker/nullness/qual/NonNull.java
new file mode 100644
index 00000000000..f25979be369
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/annotations/org/checkerframework/checker/nullness/qual/NonNull.java
@@ -0,0 +1,41 @@
+package org.checkerframework.checker.nullness.qual;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+/**
+ * {@link NonNull} is a type annotation that indicates that an expression is
+ * never {@code null}.
+ *
+ *
+ * For fields of a class, the {@link NonNull} annotation indicates that this
+ * field is never {@code null}
+ * after the class has been fully initialized. Class initialization is
+ * controlled by the Freedom Before Commitment type system, see
+ * {@link InitializationChecker} for more details.
+ *
+ *
+ * For static fields, the {@link NonNull} annotation indicates that this field
+ * is never {@code null} after the containing class is initialized.
+ *
+ *
+ * This annotation is rarely written in source code, because it is the default.
+ *
+ *
+ * This annotation is associated with the {@link AbstractNullnessChecker}.
+ *
+ * @see Nullable
+ * @see MonotonicNonNull
+ * @see AbstractNullnessChecker
+ * @checker_framework.manual #nullness-checker Nullness Checker
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+// TODO: originally it's target was: TYPE_USE, TYPE_PARAMETER
+@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE })
+public @interface NonNull {
+}
\ No newline at end of file
diff --git a/compiler/testData/foreignAnnotations/annotations/org/checkerframework/checker/nullness/qual/Nullable.java b/compiler/testData/foreignAnnotations/annotations/org/checkerframework/checker/nullness/qual/Nullable.java
new file mode 100644
index 00000000000..b60746d8f99
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/annotations/org/checkerframework/checker/nullness/qual/Nullable.java
@@ -0,0 +1,28 @@
+package org.checkerframework.checker.nullness.qual;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+/**
+ * {@link Nullable} is a type annotation that indicates that the value is not
+ * known to be non-null (see {@link NonNull}). Only if an expression has a
+ * {@link Nullable} type may it be assigned {@code null}.
+ *
+ *
+ * This annotation is associated with the {@link AbstractNullnessChecker}.
+ *
+ * @see NonNull
+ * @see MonotonicNonNull
+ * @see AbstractNullnessChecker
+ * @checker_framework.manual #nullness-checker Nullness Checker
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+// TODO: originally it's target was: TYPE_USE, TYPE_PARAMETER
+@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE })
+public @interface Nullable {
+}
\ No newline at end of file
diff --git a/compiler/testData/foreignAnnotations/annotations/org/eclipse/jdt/annotation/NonNull.java b/compiler/testData/foreignAnnotations/annotations/org/eclipse/jdt/annotation/NonNull.java
new file mode 100644
index 00000000000..d76b2e3927c
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/annotations/org/eclipse/jdt/annotation/NonNull.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2013 Stephan Herrmann and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stephan Herrmann - initial API and implementation
+ * IBM Corporation - bug fixes
+ *******************************************************************************/
+package org.eclipse.jdt.annotation;
+
+import java.lang.annotation.ElementType;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Qualifier for a reference type in a {@link ElementType#TYPE_USE TYPE_USE} position:
+ * The type that has this annotation is intended to not include the value null.
+ *
+ * If annotation based null analysis is enabled using this annotation has two consequences:
+ *
+ *
+ * - Dereferencing an expression of this type is safe, i.e., no
NullPointerException can occur at runtime.
+ * - An attempt to bind a
null value to an entity (field, local variable, method parameter or method return value)
+ * of this type is a compile time error.
+ *
+ * For the second case, diagnostics issued by the compiler should distinguish three situations:
+ *
+ * - Nullness of the value can be statically determined, the entity is definitely bound from either of:
+ *
- the value
null, or
+ * - an entity with a {@link Nullable @Nullable} type.
+ * - Nullness cannot definitely be determined, because different code branches yield different results.
+ * - Nullness cannot be determined, because other program elements are involved for which
+ * null annotations are lacking.
+ *
+ *
+ * Note: Since org.eclipse.jdt.annotation 2.0.0, the
+ * @Target is {TYPE_USE}. For the old API, see
+ *
+ * @NonNull in 1.1.0.
+ *
+ * @since 1.0
+ */
+@Documented
+@Retention(RetentionPolicy.CLASS)
+
+// TODO: originally it's targer was TYPE_USE
+@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE })
+public @interface NonNull {
+ // marker annotation with no members
+}
\ No newline at end of file
diff --git a/compiler/testData/foreignAnnotations/annotations/org/eclipse/jdt/annotation/Nullable.java b/compiler/testData/foreignAnnotations/annotations/org/eclipse/jdt/annotation/Nullable.java
new file mode 100644
index 00000000000..82684bc4cb6
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/annotations/org/eclipse/jdt/annotation/Nullable.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2013 Stephan Herrmann and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stephan Herrmann - initial API and implementation
+ * IBM Corporation - bug fixes
+ *******************************************************************************/
+package org.eclipse.jdt.annotation;
+
+import java.lang.annotation.ElementType;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Qualifier for a reference type in a {@link ElementType#TYPE_USE TYPE_USE} position:
+ * The type that has this annotation explicitly includes the value null.
+ *
+ * If annotation based null analysis is enabled using this annotation has two consequences:
+ *
+ *
+ * - Binding a
null value to an entity (field, local variable, method parameter or method return value)
+ * of this type is legal.
+ * - Dereferencing an expression of this type is unsafe, i.e., a
NullPointerException can occur at runtime.
+ *
+ *
+ * Note: Since org.eclipse.jdt.annotation 2.0.0, the
+ * @Target is {TYPE_USE}. For the old API, see
+ *
+ * @Nullable in 1.1.0.
+ *
+ * @since 1.0
+ */
+@Documented
+@Retention(RetentionPolicy.CLASS)
+// TODO: originally it's targer was TYPE_USE
+@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE })
+public @interface Nullable {
+ // marker annotation with no members
+}
\ No newline at end of file
diff --git a/compiler/testData/foreignAnnotations/tests/android.kt b/compiler/testData/foreignAnnotations/tests/android.kt
new file mode 100644
index 00000000000..5b285b83830
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/tests/android.kt
@@ -0,0 +1,43 @@
+// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
+// FILE: A.java
+
+import android.support.annotation.*;
+
+public class A {
+ @Nullable public String field = null;
+
+ @Nullable
+ public String foo(@NonNull String x, @Nullable CharSequence y) {
+ return "";
+ }
+
+ @NonNull
+ public String bar() {
+ return "";
+ }
+
+ @Nullable
+ public T baz(@NonNull T x) { return x; }
+}
+
+// FILE: main.kt
+
+fun main(a: A, a1: A) {
+ a.foo("", null)?.length
+ a.foo("", null).length
+ a.foo(null, "").length
+
+ a.bar().length
+ a.bar()!!.length
+
+ a.field?.length
+ a.field.length
+
+ a.baz("").length
+ a.baz("")?.length
+ a.baz(null).length
+
+ a1.baz("")!!.length
+ a1.baz(null)!!.length
+}
+
diff --git a/compiler/testData/foreignAnnotations/tests/android.txt b/compiler/testData/foreignAnnotations/tests/android.txt
new file mode 100644
index 00000000000..59b5fe1577b
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/tests/android.txt
@@ -0,0 +1,14 @@
+package
+
+public fun main(/*0*/ a: A, /*1*/ a1: A): kotlin.Unit
+
+public open class A*0*/ T : kotlin.Any!> {
+ public constructor A*0*/ T : kotlin.Any!>()
+ @android.support.annotation.Nullable() public final var field: kotlin.String?
+ @android.support.annotation.NonNull() public open fun bar(): kotlin.String
+ @android.support.annotation.Nullable() public open fun baz(/*0*/ @android.support.annotation.NonNull() x: T): T?
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ @android.support.annotation.Nullable() public open fun foo(/*0*/ @android.support.annotation.NonNull() x: kotlin.String, /*1*/ @android.support.annotation.Nullable() y: kotlin.CharSequence?): kotlin.String?
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
diff --git a/compiler/testData/foreignAnnotations/tests/checkerFramework.kt b/compiler/testData/foreignAnnotations/tests/checkerFramework.kt
new file mode 100644
index 00000000000..b89e1aeb1d2
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/tests/checkerFramework.kt
@@ -0,0 +1,42 @@
+// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
+// FILE: A.java
+
+import org.checkerframework.checker.nullness.qual.*;
+
+public class A {
+ @Nullable public String field = null;
+
+ @Nullable
+ public String foo(@NonNull String x, @Nullable CharSequence y) {
+ return "";
+ }
+
+ @NonNull
+ public String bar() {
+ return "";
+ }
+
+ @Nullable
+ public T baz(@NonNull T x) { return x; }
+}
+
+// FILE: main.kt
+
+fun main(a: A, a1: A) {
+ a.foo("", null)?.length
+ a.foo("", null).length
+ a.foo(null, "").length
+
+ a.bar().length
+ a.bar()!!.length
+
+ a.field?.length
+ a.field.length
+
+ a.baz("").length
+ a.baz("")?.length
+ a.baz(null).length
+
+ a1.baz("")!!.length
+ a1.baz(null)!!.length
+}
diff --git a/compiler/testData/foreignAnnotations/tests/checkerFramework.txt b/compiler/testData/foreignAnnotations/tests/checkerFramework.txt
new file mode 100644
index 00000000000..4e2a216cfa8
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/tests/checkerFramework.txt
@@ -0,0 +1,14 @@
+package
+
+public fun main(/*0*/ a: A, /*1*/ a1: A): kotlin.Unit
+
+public open class A*0*/ T : kotlin.Any!> {
+ public constructor A*0*/ T : kotlin.Any!>()
+ @org.checkerframework.checker.nullness.qual.Nullable() public final var field: kotlin.String?
+ @org.checkerframework.checker.nullness.qual.NonNull() public open fun bar(): kotlin.String
+ @org.checkerframework.checker.nullness.qual.Nullable() public open fun baz(/*0*/ @org.checkerframework.checker.nullness.qual.NonNull() x: T): T?
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ @org.checkerframework.checker.nullness.qual.Nullable() public open fun foo(/*0*/ @org.checkerframework.checker.nullness.qual.NonNull() x: kotlin.String, /*1*/ @org.checkerframework.checker.nullness.qual.Nullable() y: kotlin.CharSequence?): kotlin.String?
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
diff --git a/compiler/testData/foreignAnnotations/tests/eclipse.kt b/compiler/testData/foreignAnnotations/tests/eclipse.kt
new file mode 100644
index 00000000000..c7877f822ce
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/tests/eclipse.kt
@@ -0,0 +1,42 @@
+// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
+// FILE: A.java
+
+import org.eclipse.jdt.annotation.*;
+
+public class A {
+ @Nullable public String field = null;
+
+ @Nullable
+ public String foo(@NonNull String x, @Nullable CharSequence y) {
+ return "";
+ }
+
+ @NonNull
+ public String bar() {
+ return "";
+ }
+
+ @Nullable
+ public T baz(@NonNull T x) { return x; }
+}
+
+// FILE: main.kt
+
+fun main(a: A, a1: A) {
+ a.foo("", null)?.length
+ a.foo("", null).length
+ a.foo(null, "").length
+
+ a.bar().length
+ a.bar()!!.length
+
+ a.field?.length
+ a.field.length
+
+ a.baz("").length
+ a.baz("")?.length
+ a.baz(null).length
+
+ a1.baz("")!!.length
+ a1.baz(null)!!.length
+}
diff --git a/compiler/testData/foreignAnnotations/tests/eclipse.txt b/compiler/testData/foreignAnnotations/tests/eclipse.txt
new file mode 100644
index 00000000000..99fe9e5cd5a
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/tests/eclipse.txt
@@ -0,0 +1,14 @@
+package
+
+public fun main(/*0*/ a: A, /*1*/ a1: A): kotlin.Unit
+
+public open class A*0*/ T : kotlin.Any!> {
+ public constructor A*0*/ T : kotlin.Any!>()
+ @org.eclipse.jdt.annotation.Nullable() public final var field: kotlin.String?
+ @org.eclipse.jdt.annotation.NonNull() public open fun bar(): kotlin.String
+ @org.eclipse.jdt.annotation.Nullable() public open fun baz(/*0*/ @org.eclipse.jdt.annotation.NonNull() x: T): T?
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ @org.eclipse.jdt.annotation.Nullable() public open fun foo(/*0*/ @org.eclipse.jdt.annotation.NonNull() x: kotlin.String, /*1*/ @org.eclipse.jdt.annotation.Nullable() y: kotlin.CharSequence?): kotlin.String?
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
diff --git a/compiler/testData/foreignAnnotations/tests/findBugsSimple.kt b/compiler/testData/foreignAnnotations/tests/findBugsSimple.kt
new file mode 100644
index 00000000000..9728a0a5068
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/tests/findBugsSimple.kt
@@ -0,0 +1,33 @@
+// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
+// FILE: A.java
+
+import edu.umd.cs.findbugs.annotations.*;
+
+public class A {
+ @Nullable public String field = null;
+
+ @PossiblyNull
+ public String foo(@NonNull String x, @UnknownNullness CharSequence y) {
+ return "";
+ }
+
+ @NonNull
+ public String bar() {
+ return "";
+ }
+}
+
+// FILE: main.kt
+
+fun main(a: A) {
+ a.foo("", null)?.length
+ a.foo("", null).length
+ a.foo(null, "").length
+ a.foo(null, null).length
+
+ a.bar().length
+ a.bar()!!.length
+
+ a.field?.length
+ a.field.length
+}
diff --git a/compiler/testData/foreignAnnotations/tests/findBugsSimple.txt b/compiler/testData/foreignAnnotations/tests/findBugsSimple.txt
new file mode 100644
index 00000000000..bfadd96085e
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/tests/findBugsSimple.txt
@@ -0,0 +1,13 @@
+package
+
+public fun main(/*0*/ a: A): kotlin.Unit
+
+public open class A {
+ public constructor A()
+ @edu.umd.cs.findbugs.annotations.Nullable() public final var field: kotlin.String?
+ @edu.umd.cs.findbugs.annotations.NonNull() public open fun bar(): kotlin.String
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ @edu.umd.cs.findbugs.annotations.PossiblyNull() public open fun foo(/*0*/ @edu.umd.cs.findbugs.annotations.NonNull() x: kotlin.String, /*1*/ @edu.umd.cs.findbugs.annotations.UnknownNullness() y: kotlin.CharSequence!): kotlin.String?
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
diff --git a/compiler/testData/foreignAnnotations/tests/jsr305Simple.kt b/compiler/testData/foreignAnnotations/tests/jsr305Simple.kt
new file mode 100644
index 00000000000..0fecca7eed7
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/tests/jsr305Simple.kt
@@ -0,0 +1,33 @@
+// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
+// FILE: A.java
+
+import javax.annotation.*;
+
+public class A {
+ @Nullable public String field = null;
+
+ @Nullable
+ public String foo(@Nonnull String x, @CheckForNull CharSequence y) {
+ return "";
+ }
+
+ @Nonnull
+ public String bar() {
+ return "";
+ }
+
+}
+
+// FILE: main.kt
+
+fun main(a: A) {
+ a.foo("", null)?.length
+ a.foo("", null).length
+ a.foo(null, "").length
+
+ a.bar().length
+ a.bar()!!.length
+
+ a.field?.length
+ a.field.length
+}
diff --git a/compiler/testData/foreignAnnotations/tests/jsr305Simple.txt b/compiler/testData/foreignAnnotations/tests/jsr305Simple.txt
new file mode 100644
index 00000000000..21b6b192b14
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/tests/jsr305Simple.txt
@@ -0,0 +1,13 @@
+package
+
+public fun main(/*0*/ a: A): kotlin.Unit
+
+public open class A {
+ public constructor A()
+ @javax.annotation.Nullable() public final var field: kotlin.String?
+ @javax.annotation.Nonnull() public open fun bar(): kotlin.String
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ @javax.annotation.Nullable() public open fun foo(/*0*/ @javax.annotation.Nonnull() x: kotlin.String, /*1*/ @javax.annotation.CheckForNull() y: kotlin.CharSequence?): kotlin.String?
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
diff --git a/compiler/testData/foreignAnnotations/tests/jsr305Strange.kt b/compiler/testData/foreignAnnotations/tests/jsr305Strange.kt
new file mode 100644
index 00000000000..6c54c2ab355
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/tests/jsr305Strange.kt
@@ -0,0 +1,34 @@
+// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
+// FILE: A.java
+
+import javax.annotation.*;
+import javax.annotation.meta.*;
+
+public class A {
+ @Nonnull(when=When.UNKNOWN) public String field = null;
+
+ @Nonnull(when=When.MAYBE)
+ public String foo(@Nonnull(when=When.ALWAYS) String x, @Nonnull(when=When.NEVER) CharSequence y) {
+ return "";
+ }
+
+ @Nonnull
+ public String bar() {
+ return "";
+ }
+
+}
+
+// FILE: main.kt
+
+fun main(a: A) {
+ a.foo("", null)?.length
+ a.foo("", null).length
+ a.foo(null, "").length
+
+ a.bar().length
+ a.bar()!!.length
+
+ a.field?.length
+ a.field.length
+}
diff --git a/compiler/testData/foreignAnnotations/tests/jsr305Strange.txt b/compiler/testData/foreignAnnotations/tests/jsr305Strange.txt
new file mode 100644
index 00000000000..0323ea677e4
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/tests/jsr305Strange.txt
@@ -0,0 +1,13 @@
+package
+
+public fun main(/*0*/ a: A): kotlin.Unit
+
+public open class A {
+ public constructor A()
+ @javax.annotation.Nonnull(when = When.UNKNOWN) public final var field: kotlin.String?
+ @javax.annotation.Nonnull() public open fun bar(): kotlin.String
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ @javax.annotation.Nonnull(when = When.MAYBE) public open fun foo(/*0*/ @javax.annotation.Nonnull(when = When.ALWAYS) x: kotlin.String, /*1*/ @javax.annotation.Nonnull(when = When.NEVER) y: kotlin.CharSequence?): kotlin.String?
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
diff --git a/compiler/testData/foreignAnnotations/tests/lombokSimple.kt b/compiler/testData/foreignAnnotations/tests/lombokSimple.kt
new file mode 100644
index 00000000000..a9b68f86c45
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/tests/lombokSimple.kt
@@ -0,0 +1,20 @@
+// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
+// FILE: A.java
+
+import lombok.*;
+
+public class A {
+ @NonNull
+ public String foo(@NonNull String x) {
+ return "";
+ }
+
+}
+
+// FILE: main.kt
+
+fun main(a: A) {
+ a.foo("").length
+ a.foo("")?.length
+ a.foo(null)?.length
+}
diff --git a/compiler/testData/foreignAnnotations/tests/lombokSimple.txt b/compiler/testData/foreignAnnotations/tests/lombokSimple.txt
new file mode 100644
index 00000000000..699ecfdbaeb
--- /dev/null
+++ b/compiler/testData/foreignAnnotations/tests/lombokSimple.txt
@@ -0,0 +1,11 @@
+package
+
+public fun main(/*0*/ a: A): kotlin.Unit
+
+public open class A {
+ public constructor A()
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ @lombok.NonNull() public open fun foo(/*0*/ @lombok.NonNull() x: kotlin.String): kotlin.String
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/AbstractForeignAnnotationsTest.kt b/compiler/tests/org/jetbrains/kotlin/checkers/AbstractForeignAnnotationsTest.kt
new file mode 100644
index 00000000000..f693dbe380c
--- /dev/null
+++ b/compiler/tests/org/jetbrains/kotlin/checkers/AbstractForeignAnnotationsTest.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2010-2015 JetBrains s.r.o.
+ *
+ * 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.
+ */
+
+package org.jetbrains.kotlin.checkers
+
+import org.jetbrains.kotlin.config.CompilerConfiguration
+import org.jetbrains.kotlin.test.ConfigurationKind
+import org.jetbrains.kotlin.test.KotlinTestUtils
+import org.jetbrains.kotlin.test.MockLibraryUtil
+import org.jetbrains.kotlin.test.TestJdkKind
+import java.io.File
+
+
+abstract class AbstractForeignAnnotationsTest : AbstractDiagnosticsTest() {
+ lateinit var annotationsFile: File
+
+ override fun createCompilerConfiguration(javaFilesDir: File?): CompilerConfiguration {
+ val annotationsFile = MockLibraryUtil.compileLibraryToJar(
+ "compiler/testData/foreignAnnotations/annotations",
+ "foreign-annotations", /* addSources = */false)
+
+ return KotlinTestUtils.compilerConfigurationForTests(
+ ConfigurationKind.JDK_ONLY,
+ TestJdkKind.MOCK_JDK,
+ listOf(KotlinTestUtils.getAnnotationsJar(), annotationsFile),
+ listOf(javaFilesDir))
+ }
+}
\ No newline at end of file
diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/ForeignAnnotationsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/ForeignAnnotationsTestGenerated.java
new file mode 100644
index 00000000000..9796ae03fa0
--- /dev/null
+++ b/compiler/tests/org/jetbrains/kotlin/checkers/ForeignAnnotationsTestGenerated.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2010-2015 JetBrains s.r.o.
+ *
+ * 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.
+ */
+
+package org.jetbrains.kotlin.checkers;
+
+import com.intellij.testFramework.TestDataPath;
+import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
+import org.jetbrains.kotlin.test.KotlinTestUtils;
+import org.jetbrains.kotlin.test.TestMetadata;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.util.regex.Pattern;
+
+/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
+@SuppressWarnings("all")
+@TestMetadata("compiler/testData/foreignAnnotations/tests")
+@TestDataPath("$PROJECT_ROOT")
+@RunWith(JUnit3RunnerWithInners.class)
+public class ForeignAnnotationsTestGenerated extends AbstractForeignAnnotationsTest {
+ public void testAllFilesPresentInTests() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/foreignAnnotations/tests"), Pattern.compile("^(.+)\\.kt$"), true);
+ }
+
+ @TestMetadata("android.kt")
+ public void testAndroid() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/android.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("checkerFramework.kt")
+ public void testCheckerFramework() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/checkerFramework.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("eclipse.kt")
+ public void testEclipse() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/eclipse.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("findBugsSimple.kt")
+ public void testFindBugsSimple() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/findBugsSimple.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("jsr305Simple.kt")
+ public void testJsr305Simple() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/jsr305Simple.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("jsr305Strange.kt")
+ public void testJsr305Strange() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/jsr305Strange.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("lombokSimple.kt")
+ public void testLombokSimple() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/lombokSimple.kt");
+ doTest(fileName);
+ }
+}
diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.kt
index 5e2edae26a0..2dced1653fa 100644
--- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.kt
+++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.kt
@@ -19,11 +19,26 @@ package org.jetbrains.kotlin.load.java
import org.jetbrains.kotlin.name.FqName
val NULLABLE_ANNOTATIONS = listOf(
- JvmAnnotationNames.JETBRAINS_NULLABLE_ANNOTATION
+ JvmAnnotationNames.JETBRAINS_NULLABLE_ANNOTATION,
+ FqName("android.support.annotation.Nullable"),
+ FqName("org.eclipse.jdt.annotation.Nullable"),
+ FqName("org.checkerframework.checker.nullness.qual.Nullable"),
+ FqName("javax.annotation.Nullable"),
+ FqName("javax.annotation.CheckForNull"),
+ FqName("edu.umd.cs.findbugs.annotations.CheckForNull"),
+ FqName("edu.umd.cs.findbugs.annotations.Nullable"),
+ FqName("edu.umd.cs.findbugs.annotations.PossiblyNull")
)
+val JAVAX_NONNULL_ANNOTATION = FqName("javax.annotation.Nonnull")
+
val NOT_NULL_ANNOTATIONS = listOf(
- JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION
+ JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION,
+ FqName("edu.umd.cs.findbugs.annotations.NonNull"),
+ FqName("android.support.annotation.NonNull"),
+ FqName("org.eclipse.jdt.annotation.NonNull"),
+ FqName("org.checkerframework.checker.nullness.qual.NonNull"),
+ FqName("lombok.NonNull")
)
val READ_ONLY_ANNOTATIONS = listOf(
@@ -37,5 +52,6 @@ val MUTABLE_ANNOTATIONS = listOf(
// When these annotations appear on a declaration, they are copied to the _type_ of the declaration, becoming type annotations
// See also DescriptorRendererOptions#excludedTypeAnnotationClasses
val ANNOTATIONS_COPIED_TO_TYPES: Set = listOf(
- NULLABLE_ANNOTATIONS, NOT_NULL_ANNOTATIONS, READ_ONLY_ANNOTATIONS, MUTABLE_ANNOTATIONS
+ NULLABLE_ANNOTATIONS, NOT_NULL_ANNOTATIONS, READ_ONLY_ANNOTATIONS, MUTABLE_ANNOTATIONS,
+ listOf(JAVAX_NONNULL_ANNOTATION)
).flatMap { it }.toSet()
diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/typeQualifiers.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/typeQualifiers.kt
index 41144882688..2c47062bc13 100644
--- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/typeQualifiers.kt
+++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/typeQualifiers.kt
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.load.java.typeEnhancement
+import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.load.java.*
import org.jetbrains.kotlin.load.java.typeEnhancement.MutabilityQualifier.MUTABLE
@@ -64,11 +65,32 @@ private fun KotlinType.extractQualifiers(): JavaTypeQualifiers {
private fun Annotations.extractQualifiers(): JavaTypeQualifiers {
fun List.ifPresent(qualifier: T) = if (any { findAnnotation(it) != null}) qualifier else null
- fun singleNotNull(x: T?, y: T?) = if (x == null || y == null) x ?: y else null
+
+ // These two overloads are just for sake of optimization as in most cases last parameter in second overload is null
+ fun uniqueNotNull(x: T?, y: T?) = if (x == null || y == null || x == y) x ?: y else null
+ fun uniqueNotNull(a: T?, b: T?, c: T?) =
+ if (c == null)
+ uniqueNotNull(a, b)
+ else
+ listOf(a, b, c).filterNotNull().toSet().singleOrNull()
+
+ // Javax/FundBugs NonNull annotation has parameter `when` that determines actual nullability
+ fun FqName.extractQualifierFromAnnotationWithWhen(): NullabilityQualifier? {
+ val annotationDescriptor = findAnnotation(this) ?: return null
+ return annotationDescriptor.allValueArguments.values.singleOrNull()?.value?.let {
+ enumEntryDescriptor ->
+ if (enumEntryDescriptor !is ClassDescriptor) return@let null
+ if (enumEntryDescriptor.name.asString() == "ALWAYS") NOT_NULL else NULLABLE
+ } ?: NOT_NULL
+ }
return JavaTypeQualifiers(
- singleNotNull(NULLABLE_ANNOTATIONS.ifPresent(NULLABLE), NOT_NULL_ANNOTATIONS.ifPresent(NOT_NULL)),
- singleNotNull(READ_ONLY_ANNOTATIONS.ifPresent(READ_ONLY), MUTABLE_ANNOTATIONS.ifPresent(MUTABLE))
+ uniqueNotNull(
+ NULLABLE_ANNOTATIONS.ifPresent(NULLABLE),
+ NOT_NULL_ANNOTATIONS.ifPresent(NOT_NULL),
+ JAVAX_NONNULL_ANNOTATION.extractQualifierFromAnnotationWithWhen()
+ ),
+ uniqueNotNull(READ_ONLY_ANNOTATIONS.ifPresent(READ_ONLY), MUTABLE_ANNOTATIONS.ifPresent(MUTABLE))
)
}
diff --git a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRenderer.kt b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRenderer.kt
index 94f13f8af71..e848330ef77 100644
--- a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRenderer.kt
+++ b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRenderer.kt
@@ -198,7 +198,22 @@ object ExcludedTypeAnnotations {
FqName("org.jetbrains.annotations.ReadOnly"),
FqName("org.jetbrains.annotations.Mutable"),
FqName("org.jetbrains.annotations.NotNull"),
- FqName("org.jetbrains.annotations.Nullable"))
+ FqName("org.jetbrains.annotations.Nullable"),
+ FqName("android.support.annotation.Nullable"),
+ FqName("android.support.annotation.NonNull"),
+ FqName("org.eclipse.jdt.annotation.Nullable"),
+ FqName("org.eclipse.jdt.annotation.NonNull"),
+ FqName("org.checkerframework.checker.nullness.qual.Nullable"),
+ FqName("org.checkerframework.checker.nullness.qual.NonNull"),
+ FqName("javax.annotation.Nonnull"),
+ FqName("javax.annotation.Nullable"),
+ FqName("javax.annotation.CheckForNull"),
+ FqName("edu.umd.cs.findbugs.annotations.NonNull"),
+ FqName("edu.umd.cs.findbugs.annotations.CheckForNull"),
+ FqName("edu.umd.cs.findbugs.annotations.Nullable"),
+ FqName("edu.umd.cs.findbugs.annotations.PossiblyNull"),
+ FqName("lombok.NonNull")
+ )
val internalAnnotationsForResolve = setOf(
FqName("kotlin.internal.NoInfer"),
diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt
index efa690b46ac..01c4585d414 100644
--- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt
+++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt
@@ -162,6 +162,10 @@ fun main(args: Array) {
model("diagnostics/testsWithJsStdLibAndBackendCompilation")
}
+ testClass() {
+ model("foreignAnnotations/tests")
+ }
+
testClass() {
model("resolve", extension = "resolve")
}
diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/conventionNameCalls/ReplaceContainsIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/conventionNameCalls/ReplaceContainsIntention.kt
index 8fe523e541a..33c3db448e3 100644
--- a/idea/src/org/jetbrains/kotlin/idea/intentions/conventionNameCalls/ReplaceContainsIntention.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/intentions/conventionNameCalls/ReplaceContainsIntention.kt
@@ -63,7 +63,7 @@ class ReplaceContainsIntention : SelfTargetingRangeIntention