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: + *

+ *
    + *
  1. Dereferencing an expression of this type is safe, i.e., no NullPointerException can occur at runtime.
  2. + *
  3. 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.
  4. + *
+ * For the second case, diagnostics issued by the compiler should distinguish three situations: + *
    + *
  1. 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.
  2. + *
  3. Nullness cannot definitely be determined, because different code branches yield different results.
  4. + *
  5. Nullness cannot be determined, because other program elements are involved for which + * null annotations are lacking.
  6. + *
+ *

+ * 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: + *

+ *
    + *
  1. Binding a null value to an entity (field, local variable, method parameter or method return value) + * of this type is legal.
  2. + *
  3. Dereferencing an expression of this type is unsafe, i.e., a NullPointerException can occur at runtime.
  4. + *
+ *

+ * 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 { + public constructor A() + @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 { + public constructor A() + @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 { + public constructor A() + @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