1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 @file:Suppress("ALL") 18 19 package com.android.tools.metalava 20 21 import org.junit.Test 22 23 class Java9LanguageFeaturesTest : DriverTest() { 24 @Test Private Interface Methodnull25 fun `Private Interface Method`() { 26 // Basic class; also checks that default constructor is made explicit 27 check( 28 format = FileFormat.V1, 29 checkCompilation = false, // Not compiling with JDK 9 yet 30 sourceFiles = arrayOf( 31 java( 32 """ 33 package test.pkg; 34 35 public interface Person { 36 String name(); 37 private String reverse(String s) { 38 return new StringBuilder(s).reverse().toString(); 39 } 40 } 41 """ 42 ) 43 ), 44 api = """ 45 package test.pkg { 46 public interface Person { 47 method public String name(); 48 } 49 } 50 """, 51 extraArguments = arrayOf(ARG_JAVA_SOURCE, "1.9") 52 ) 53 } 54 55 @Test Kotlin language levelnull56 fun `Kotlin language level`() { 57 // See https://kotlinlang.org/docs/reference/whatsnew13.html 58 check( 59 format = FileFormat.V1, 60 sourceFiles = arrayOf( 61 kotlin( 62 """ 63 package test.pkg 64 interface Foo { 65 companion object { 66 @JvmField 67 const val answer: Int = 42 68 @JvmStatic 69 fun sayHello() { 70 println("Hello, world!") 71 } 72 } 73 } 74 """ 75 ) 76 ), 77 api = 78 """ 79 package test.pkg { 80 public interface Foo { 81 method public default static void sayHello(); 82 field @NonNull public static final test.pkg.Foo.Companion Companion; 83 field public static final int answer = 42; // 0x2a 84 } 85 public static final class Foo.Companion { 86 method public void sayHello(); 87 } 88 } 89 """, 90 // The above source uses 1.3 features, though UAST currently 91 // seems to still treat it as 1.3 despite being passed 1.2 92 extraArguments = arrayOf(ARG_KOTLIN_SOURCE, "1.2") 93 ) 94 } 95 96 @Test Basic class signature extractionnull97 fun `Basic class signature extraction`() { 98 // Basic class; also checks that default constructor is made explicit 99 check( 100 format = FileFormat.V1, 101 checkCompilation = false, // Not compiling with JDK 9 yet 102 sourceFiles = arrayOf( 103 java( 104 """ 105 package libcore.internal; 106 107 import java.io.ByteArrayInputStream; 108 import java.io.ByteArrayOutputStream; 109 import java.io.IOException; 110 import java.io.InputStream; 111 import java.util.ArrayList; 112 import java.util.Arrays; 113 import java.util.List; 114 import java.util.Objects; 115 import java.util.concurrent.atomic.AtomicReference; 116 117 public class Java9LanguageFeatures { 118 119 public interface Person { 120 String name(); 121 122 default boolean isPalindrome() { 123 return name().equals(reverse(name())); 124 } 125 126 default boolean isPalindromeIgnoreCase() { 127 return name().equalsIgnoreCase(reverse(name())); 128 } 129 130 // Language feature: private interface method 131 private String reverse(String s) { 132 return new StringBuilder(s).reverse().toString(); 133 } 134 } 135 136 @SafeVarargs 137 public static<T> String toListString(T... values) { 138 return toString(values).toString(); 139 } 140 141 // Language feature: @SafeVarargs on private methods 142 @SafeVarargs 143 private static<T> List<String> toString(T... values) { 144 List<String> result = new ArrayList<>(); 145 for (T value : values) { 146 result.add(value.toString()); 147 } 148 return result; 149 } 150 151 public <T> AtomicReference<T> createReference(T content) { 152 // Language feature: <> on anonymous class 153 //noinspection unchecked 154 return new AtomicReference<>(content) { }; 155 } 156 157 public static byte[] copy(byte[] bytes) throws IOException { 158 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 159 InputStream inputStream = new ByteArrayInputStream(bytes); 160 try (inputStream) { // Language feature: try on effectively-final variable 161 int value; 162 while ((value = inputStream.read()) != -1) { 163 byteArrayOutputStream.write(value); 164 } 165 } 166 return byteArrayOutputStream.toByteArray(); 167 } 168 } 169 """ 170 ) 171 ), 172 api = """ 173 package libcore.internal { 174 public class Java9LanguageFeatures { 175 ctor public Java9LanguageFeatures(); 176 method public static byte[] copy(byte[]) throws java.io.IOException; 177 method public <T> java.util.concurrent.atomic.AtomicReference<T> createReference(T); 178 method @java.lang.SafeVarargs public static <T> String toListString(T...); 179 } 180 public static interface Java9LanguageFeatures.Person { 181 method public default boolean isPalindrome(); 182 method public default boolean isPalindromeIgnoreCase(); 183 method public String name(); 184 } 185 } 186 """, 187 extraArguments = arrayOf(ARG_JAVA_SOURCE, "1.9") 188 ) 189 } 190 191 @Test Using JDK APIsnull192 fun `Using JDK APIs`() { 193 // Non-Android example 194 val jdk = System.getProperty("java.home") ?: error("Expected java.home to be set") 195 check( 196 format = FileFormat.V2, 197 sourceFiles = arrayOf( 198 java( 199 """ 200 package test.pkg; 201 import javax.swing.JButton; 202 public class SwingTest extends JButton { 203 public JButton button; 204 } 205 """ 206 ) 207 ), 208 api = 209 """ 210 package test.pkg { 211 public class SwingTest extends javax.swing.JButton { 212 ctor public SwingTest(); 213 field public javax.swing.JButton button; 214 } 215 } 216 """, 217 extraArguments = arrayOf(ARG_JDK_HOME, jdk) 218 ) 219 } 220 } 221