1 /* 2 * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.lang.model; 27 28 import java.util.Collections; 29 import java.util.Set; 30 import java.util.HashSet; 31 32 /** 33 * Source versions of the Java™ programming language. 34 * 35 * See the appropriate edition of 36 * <cite>The Java™ Language Specification</cite> 37 * for information about a particular source version. 38 * 39 * <p>Note that additional source version constants will be added to 40 * model future releases of the language. 41 * 42 * @author Joseph D. Darcy 43 * @author Scott Seligman 44 * @author Peter von der Ahé 45 * @since 1.6 46 */ 47 public enum SourceVersion { 48 /* 49 * Summary of language evolution 50 * 1.1: nested classes 51 * 1.2: strictfp 52 * 1.3: no changes 53 * 1.4: assert 54 * 1.5: annotations, generics, autoboxing, var-args... 55 * 1.6: no changes 56 * 1.7: diamond syntax, try-with-resources, etc. 57 * 1.8: lambda expressions and default methods 58 * 9: modules, small cleanups to 1.7 and 1.8 changes 59 * 10: local-variable type inference (var) 60 * 11: local-variable syntax for lambda parameters 61 * 12: no changes (switch expressions in preview) 62 * 13: no changes (switch expressions and text blocks in preview) 63 * 14: switch expressions 64 * 15: TBD 65 */ 66 67 /** 68 * The original version. 69 * 70 * The language described in 71 * <cite>The Java™ Language Specification, First Edition</cite>. 72 */ 73 RELEASE_0, 74 75 /** 76 * The version recognized by the Java Platform 1.1. 77 * 78 * The language is {@code RELEASE_0} augmented with nested classes as described in the 1.1 update to 79 * <cite>The Java™ Language Specification, First Edition</cite>. 80 */ 81 RELEASE_1, 82 83 /** 84 * The version recognized by the Java 2 Platform, Standard Edition, 85 * v 1.2. 86 * 87 * The language described in 88 * <cite>The Java™ Language Specification, 89 * Second Edition</cite>, which includes the {@code 90 * strictfp} modifier. 91 */ 92 RELEASE_2, 93 94 /** 95 * The version recognized by the Java 2 Platform, Standard Edition, 96 * v 1.3. 97 * 98 * No major changes from {@code RELEASE_2}. 99 */ 100 RELEASE_3, 101 102 /** 103 * The version recognized by the Java 2 Platform, Standard Edition, 104 * v 1.4. 105 * 106 * Added a simple assertion facility. 107 */ 108 RELEASE_4, 109 110 /** 111 * The version recognized by the Java 2 Platform, Standard 112 * Edition 5.0. 113 * 114 * The language described in 115 * <cite>The Java™ Language Specification, 116 * Third Edition</cite>. First release to support 117 * generics, annotations, autoboxing, var-args, enhanced {@code 118 * for} loop, and hexadecimal floating-point literals. 119 */ 120 RELEASE_5, 121 122 /** 123 * The version recognized by the Java Platform, Standard Edition 124 * 6. 125 * 126 * No major changes from {@code RELEASE_5}. 127 */ 128 RELEASE_6, 129 130 /** 131 * The version recognized by the Java Platform, Standard Edition 132 * 7. 133 * 134 * Additions in this release include, diamond syntax for 135 * constructors, {@code try}-with-resources, strings in switch, 136 * binary literals, and multi-catch. 137 * @since 1.7 138 */ 139 RELEASE_7, 140 141 /** 142 * The version recognized by the Java Platform, Standard Edition 143 * 8. 144 * 145 * Additions in this release include lambda expressions and default methods. 146 * @since 1.8 147 */ 148 RELEASE_8, 149 150 /** 151 * The version recognized by the Java Platform, Standard Edition 152 * 9. 153 * 154 * Additions in this release include modules and removal of a 155 * single underscore from the set of legal identifier names. 156 * 157 * @since 9 158 */ 159 RELEASE_9, 160 161 /** 162 * The version recognized by the Java Platform, Standard Edition 163 * 10. 164 * 165 * Additions in this release include local-variable type inference 166 * ({@code var}). 167 * 168 * @since 10 169 */ 170 RELEASE_10, 171 172 /** 173 * The version recognized by the Java Platform, Standard Edition 174 * 11. 175 * 176 * Additions in this release include local-variable syntax for 177 * lambda parameters. 178 * 179 * @since 11 180 */ 181 RELEASE_11, 182 183 /** 184 * The version recognized by the Java Platform, Standard Edition 185 * 12. 186 * 187 * @since 12 188 */ 189 RELEASE_12, 190 191 /** 192 * The version recognized by the Java Platform, Standard Edition 193 * 13. 194 * 195 * @since 13 196 */ 197 RELEASE_13, 198 199 /** 200 * The version recognized by the Java Platform, Standard Edition 201 * 14. 202 * 203 * Additions in this release include switch expressions. 204 * 205 * @since 14 206 */ 207 RELEASE_14, 208 209 /** 210 * The version recognized by the Java Platform, Standard Edition 211 * 15. 212 * 213 * Additions in this release include switch expressions. 214 * 215 * @since 15 216 */ 217 RELEASE_15; 218 219 // Note that when adding constants for newer releases, the 220 // behavior of latest() and latestSupported() must be updated too. 221 222 /** 223 * Returns the latest source version that can be modeled. 224 * 225 * @return the latest source version that can be modeled 226 */ 227 public static SourceVersion latest() { 228 return RELEASE_15; 229 } 230 231 private static final SourceVersion latestSupported = getLatestSupported(); 232 233 /* 234 * The integer version to enum constant mapping implemented by 235 * this method assumes the JEP 322: "Time-Based Release 236 * Versioning" scheme is in effect. This scheme began in JDK 237 * 10. If the JDK versioning scheme is revised, this method may 238 * need to be updated accordingly. 239 */ 240 private static SourceVersion getLatestSupported() { 241 int intVersion = Runtime.version().feature(); 242 return (intVersion >= 11) ? 243 valueOf("RELEASE_" + Math.min(15, intVersion)): 244 RELEASE_10; 245 } 246 247 /** 248 * Returns the latest source version fully supported by the 249 * current execution environment. {@code RELEASE_9} or later must 250 * be returned. 251 * 252 * @apiNote This method is included alongside {@link latest} to 253 * allow identification of situations where the language model API 254 * is running on a platform version different than the latest 255 * version modeled by the API. One way that sort of situation can 256 * occur is if an IDE or similar tool is using the API to model 257 * source version <i>N</i> while running on platform version 258 * (<i>N</i> - 1). Running in this configuration is 259 * supported by the API. Running an API on platform versions 260 * earlier than (<i>N</i> - 1) or later than <i>N</i> 261 * may or may not work as an implementation detail. If an 262 * annotation processor was generating code to run under the 263 * current execution environment, the processor should only use 264 * platform features up to the {@code latestSupported} release, 265 * which may be earlier than the {@code latest} release. 266 * 267 * @return the latest source version that is fully supported 268 */ 269 public static SourceVersion latestSupported() { 270 return latestSupported; 271 } 272 273 /** 274 * Returns whether or not {@code name} is a syntactically valid 275 * identifier (simple name) or keyword in the latest source 276 * version. The method returns {@code true} if the name consists 277 * of an initial character for which {@link 278 * Character#isJavaIdentifierStart(int)} returns {@code true}, 279 * followed only by characters for which {@link 280 * Character#isJavaIdentifierPart(int)} returns {@code true}. 281 * This pattern matches regular identifiers, keywords, restricted 282 * keywords, restricted identifiers and the literals {@code "true"}, 283 * {@code "false"}, {@code "null"}. 284 * 285 * The method returns {@code false} for all other strings. 286 * 287 * @param name the string to check 288 * @return {@code true} if this string is a 289 * syntactically valid identifier or keyword, {@code false} 290 * otherwise. 291 */ 292 public static boolean isIdentifier(CharSequence name) { 293 String id = name.toString(); 294 295 if (id.length() == 0) { 296 return false; 297 } 298 int cp = id.codePointAt(0); 299 if (!Character.isJavaIdentifierStart(cp)) { 300 return false; 301 } 302 for (int i = Character.charCount(cp); 303 i < id.length(); 304 i += Character.charCount(cp)) { 305 cp = id.codePointAt(i); 306 if (!Character.isJavaIdentifierPart(cp)) { 307 return false; 308 } 309 } 310 return true; 311 } 312 313 /** 314 * Returns whether or not {@code name} is a syntactically valid 315 * qualified name in the latest source version. Unlike {@link 316 * #isIdentifier isIdentifier}, this method returns {@code false} 317 * for keywords, boolean literals, and the null literal. 318 * 319 * This method returns {@code true} for <i>restricted 320 * keywords</i> and <i>restricted identifiers</i> 321 * 322 * @param name the string to check 323 * @return {@code true} if this string is a 324 * syntactically valid name, {@code false} otherwise. 325 * @jls 3.9 Keywords 326 * @jls 6.2 Names and Identifiers 327 */ 328 public static boolean isName(CharSequence name) { 329 return isName(name, latest()); 330 } 331 332 /** 333 * Returns whether or not {@code name} is a syntactically valid 334 * qualified name in the given source version. Unlike {@link 335 * #isIdentifier isIdentifier}, this method returns {@code false} 336 * for keywords, boolean literals, and the null literal. 337 * 338 * This method returns {@code true} for <i>restricted 339 * keywords</i> and <i>restricted identifiers</i> 340 * 341 * @param name the string to check 342 * @param version the version to use 343 * @return {@code true} if this string is a 344 * syntactically valid name, {@code false} otherwise. 345 * @jls 3.9 Keywords 346 * @jls 6.2 Names and Identifiers 347 * @since 9 348 */ 349 public static boolean isName(CharSequence name, SourceVersion version) { 350 String id = name.toString(); 351 352 for(String s : id.split("\\.", -1)) { 353 if (!isIdentifier(s) || isKeyword(s, version)) 354 return false; 355 } 356 return true; 357 } 358 359 /** 360 * Returns whether or not {@code s} is a keyword, boolean literal, 361 * or null literal in the latest source version. 362 * This method returns {@code false} for <i>restricted 363 * keywords</i> and <i>restricted identifiers</i>. 364 * 365 * @param s the string to check 366 * @return {@code true} if {@code s} is a keyword, or boolean 367 * literal, or null literal, {@code false} otherwise. 368 * @jls 3.9 Keywords 369 * @jls 3.10.3 Boolean Literals 370 * @jls 3.10.7 The Null Literal 371 */ 372 public static boolean isKeyword(CharSequence s) { 373 return isKeyword(s, latest()); 374 } 375 376 /** 377 * Returns whether or not {@code s} is a keyword, boolean literal, 378 * or null literal in the given source version. 379 * This method returns {@code false} for <i>restricted 380 * keywords</i> and <i>restricted identifiers</i>. 381 * 382 * @param s the string to check 383 * @param version the version to use 384 * @return {@code true} if {@code s} is a keyword, or boolean 385 * literal, or null literal, {@code false} otherwise. 386 * @jls 3.9 Keywords 387 * @jls 3.10.3 Boolean Literals 388 * @jls 3.10.7 The Null Literal 389 * @since 9 390 */ 391 public static boolean isKeyword(CharSequence s, SourceVersion version) { 392 String id = s.toString(); 393 switch(id) { 394 // A trip through history 395 case "strictfp": 396 return version.compareTo(RELEASE_2) >= 0; 397 398 case "assert": 399 return version.compareTo(RELEASE_4) >= 0; 400 401 case "enum": 402 return version.compareTo(RELEASE_5) >= 0; 403 404 case "_": 405 return version.compareTo(RELEASE_9) >= 0; 406 407 // Keywords common across versions 408 409 // Modifiers 410 case "public": case "protected": case "private": 411 case "abstract": case "static": case "final": 412 case "transient": case "volatile": case "synchronized": 413 case "native": 414 415 // Declarations 416 case "class": case "interface": case "extends": 417 case "package": case "throws": case "implements": 418 419 // Primitive types and void 420 case "boolean": case "byte": case "char": 421 case "short": case "int": case "long": 422 case "float": case "double": 423 case "void": 424 425 // Control flow 426 case "if": case "else": 427 case "try": case "catch": case "finally": 428 case "do": case "while": 429 case "for": case "continue": 430 case "switch": case "case": case "default": 431 case "break": case "throw": case "return": 432 433 // Other keywords 434 case "this": case "new": case "super": 435 case "import": case "instanceof": 436 437 // Forbidden! 438 case "goto": case "const": 439 440 // literals 441 case "null": case "true": case "false": 442 return true; 443 444 default: 445 return false; 446 } 447 } 448 }