blob: 958e7b6b65f295ade5c0f58b9d864044d4705cf6 [file] [log] [blame]
/*
* Copyright (C) 2018 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 com.android.tools.metalava
import com.android.tools.metalava.testing.java
import org.junit.Test
class AndroidApiChecksTest : DriverTest() {
@Test
fun `Flag TODO documentation`() {
check(
expectedIssues =
"""
src/android/pkg/Test.java:4: lint: Documentation mentions 'TODO' [Todo]
src/android/pkg/Test.java:6: lint: Documentation mentions 'TODO' [Todo]
""",
sourceFiles =
arrayOf(
// Nothing in outside of Android
java(
"""
package test.pkg;
/** TODO: Some comment here */
public class Ignored1 {
}
"""
),
// Nothing in android.icu
java(
"""
package android.icu;
/** TODO: Some comment here */
public class Ignored2 {
}
"""
),
java(
"""
package android.pkg;
/** TODO: Some comment here */
public class Test {
/** TODO(ldap): Some comment here */
public void fun() {
// TODO: Code doesn't count
}
}
"""
)
)
)
}
@Test
fun `Document Permissions`() {
check(
expectedIssues =
"""
src/android/pkg/PermissionTest.java:14: lint: Method 'test0' documentation mentions permissions without declaring @RequiresPermission [RequiresPermission]
src/android/pkg/PermissionTest.java:21: lint: Method 'test1' documentation mentions permissions already declared by @RequiresPermission [RequiresPermission]
""",
sourceFiles =
arrayOf(
java(
"""
package android.pkg;
import android.Manifest;
import android.annotation.RequiresPermission;
public class PermissionTest {
// Flag methods that talk about permissions in the documentation
// but isn't annotated
/**
* Blah blah.
* Requires permission: {@link android.Manifest.permission#READ_PHONE_STATE}
*/
public void test0() {
}
// Flag methods which has permission annotation, but has
// documentation mentioning other permissions that are not listed
/** Blah blah blah ACCESS_COARSE_LOCATION */
@RequiresPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
public void test1() {
}
// TODO: Flag methods which has permission annotation, but where one
// of the permissions is annotated but not mentioned
@RequiresPermission(allOf = Manifest.permission.ACCESS_COARSE_LOCATION)
public void test2() {
}
}
"""
),
java(
"""
package android;
public abstract class Manifest {
public static final class permission {
public static final String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION";
public static final String ACCESS_FINE_LOCATION = "android.permission.ACCESS_FINE_LOCATION";
public static final String ACCOUNT_MANAGER = "android.permission.ACCOUNT_MANAGER";
}
}
"""
),
requiresPermissionSource
)
)
}
@Test
fun `Document Intent Actions`() {
check(
expectedIssues =
"""
src/android/pkg/IntentActionTest.java:30: lint: Field 'BAR_FOO_ERROR_ACTION' is missing @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) [SdkConstant]
src/android/pkg/IntentActionTest.java:19: lint: Field 'FOO_BAR_ERROR_ACTION' is missing @BroadcastBehavior [BroadcastBehavior]
src/android/pkg/IntentActionTest.java:19: lint: Field 'FOO_BAR_ERROR_ACTION' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) [SdkConstant]
""",
sourceFiles =
arrayOf(
java(
"""
package android.pkg;
import android.Manifest;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.BroadcastBehavior;
public class IntentActionTest {
/**
* Broadcast Action: Foo Bar has started.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@BroadcastBehavior(includeBackground = true)
public static final String FOO_BAR_OK_ACTION = "android.something.FOO_BAR";
/**
* Broadcast Action: Foo Bar has started.
*/
public static final String FOO_BAR_ERROR_ACTION = "android.something.FOO_BAR";
/**
* Activity Action: Bar the Foo.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String BAR_FOO_OK_ACTION = "android.something.BAR_FOO";
/**
* Activity Action: Bar the Foo.
*/
public static final String BAR_FOO_ERROR_ACTION = "android.something.BAR_FOO";
}
"""
),
sdkConstantSource,
broadcastBehaviorSource
)
)
}
@Test
fun `Check Warnings for missing nullness annotations`() {
check(
expectedIssues =
"""
src/android/pkg/NullMentions.java:18: warning: Parameter 'param1' of 'method3' documentation mentions 'null' without declaring @NonNull or @Nullable [Nullable]
src/android/pkg/NullMentions.java:21: warning: Return value of 'method4' documentation mentions 'null' without declaring @NonNull or @Nullable [Nullable]
src/android/pkg/NullMentions.java:9: warning: Field 'field2' documentation mentions 'null' without declaring @NonNull or @Nullable [Nullable]
""",
extraArguments = arrayOf(ARG_WARNING, "Nullable"), // Hidden by default
sourceFiles =
arrayOf(
java(
"""
package android.pkg;
import android.annotation.Nullable;
public class NullMentions {
/** Blah blah */
public Object field1;
/** Blah blah. Never null. */
public Object field2;
/** Blah blah */
public Object method1() { return null; }
/** Blah blah. Sometimes null. */
public Object method2() { return null; }
/** Blah blah. Never null. */
public Object method2(Object param1) { return null; }
/** Blah blah. Never null.
* @param param1 Sometimes null. */
public Object method3(Object param1) { return null; }
/** Blah blah. Never null.
* @return Sometimes null. */
public Object method4(Object param1) { return null; }
/** Blah blah. Never null.
* @param param1 Sometimes null.
* @return Sometimes null. */
public @Nullable Object method5(@Nullable Object param1) { return null; }
}
"""
),
nullableSource
)
)
}
@Test
fun `Check IntDef Warnings`() {
check(
expectedIssues =
"""
src/android/pkg/NullMentions.java:16: warning: Field 'field1' documentation mentions constants without declaring an @IntDef [IntDef]
""",
extraArguments = arrayOf(ARG_WARNING, "IntDef"), // Hidden by default
sourceFiles =
arrayOf(
java(
"""
package android.pkg;
import android.annotation.IntDef;
import android.annotation.Nullable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
public class NullMentions {
@IntDef({CONSTANT_ONE, CONSTANT_TWO})
@Retention(RetentionPolicy.SOURCE)
private @interface MyStyle {}
public static final int CONSTANT_ONE = 1;
public static final int CONSTANT_TWO = 12;
/** Should be CONSTANT_ONE or CONSTANT_TWO */
public int field1; // WARN
/** Should be CONSTANT_ONE or CONSTANT_TWO */
@MyStyle
public int field2; // OK
}
"""
),
intDefAnnotationSource,
nullableSource
)
)
}
}