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 */ 65 66 /** 67 * The original version. 68 * 69 * The language described in 70 * <cite>The Java™ Language Specification, First Edition</cite>. 71 */ 72 RELEASE_0, 73 74 /** 75 * The version recognized by the Java Platform 1.1. 76 * 77 * The language is {@code RELEASE_0} augmented with nested classes as described in the 1.1 update to 78 * <cite>The Java™ Language Specification, First Edition</cite>. 79 */ 80 RELEASE_1, 81 82 /** 83 * The version recognized by the Java 2 Platform, Standard Edition, 84 * v 1.2. 85 * 86 * The language described in 87 * <cite>The Java™ Language Specification, 88 * Second Edition</cite>, which includes the {@code 89 * strictfp} modifier. 90 */ 91 RELEASE_2, 92 93 /** 94 * The version recognized by the Java 2 Platform, Standard Edition, 95 * v 1.3. 96 * 97 * No major changes from {@code RELEASE_2}. 98 */ 99 RELEASE_3, 100 101 /** 102 * The version recognized by the Java 2 Platform, Standard Edition, 103 * v 1.4. 104 * 105 * Added a simple assertion facility. 106 */ 107 RELEASE_4, 108 109 /** 110 * The version recognized by the Java 2 Platform, Standard 111 * Edition 5.0. 112 * 113 * The language described in 114 * <cite>The Java™ Language Specification, 115 * Third Edition</cite>. First release to support 116 * generics, annotations, autoboxing, var-args, enhanced {@code 117 * for} loop, and hexadecimal floating-point literals. 118 */ 119 RELEASE_5, 120 121 /** 122 * The version recognized by the Java Platform, Standard Edition 123 * 6. 124 * 125 * No major changes from {@code RELEASE_5}. 126 */ 127 RELEASE_6, 128 129 /** 130 * The version recognized by the Java Platform, Standard Edition 131 * 7. 132 * 133 * Additions in this release include, diamond syntax for 134 * constructors, {@code try}-with-resources, strings in switch, 135 * binary literals, and multi-catch. 136 * @since 1.7 137 */ 138 RELEASE_7, 139 140 /** 141 * The version recognized by the Java Platform, Standard Edition 142 * 8. 143 * 144 * Additions in this release include lambda expressions and default methods. 145 * @since 1.8 146 */ 147 RELEASE_8, 148 149 /** 150 * The version recognized by the Java Platform, Standard Edition 151 * 9. 152 * 153 * Additions in this release include modules and removal of a 154 * single underscore from the set of legal identifier names. 155 * 156 * @since 9 157 */ 158 RELEASE_9, 159 160 /** 161 * The version recognized by the Java Platform, Standard Edition 162 * 10. 163 * 164 * Additions in this release include local-variable type inference 165 * ({@code var}). 166 * 167 * @since 10 168 */ 169 RELEASE_10, 170 171 /** 172 * The version recognized by the Java Platform, Standard Edition 173 * 11. 174 * 175 * Additions in this release include local-variable syntax for 176 * lambda parameters. 177 * 178 * @since 11 179 */ 180 RELEASE_11, 181 182 /** 183 * The version recognized by the Java Platform, Standard Edition 184 * 12. 185 * 186 * @since 12 187 */ 188 RELEASE_12, 189 190 /** 191 * The version recognized by the Java Platform, Standard Edition 192 * 13. 193 * 194 * @since 13 195 */ 196 RELEASE_13, 197 198 /** 199 * The version recognized by the Java Platform, Standard Edition 200 * 14. 201 * 202 * Additions in this release include switch expressions. 203 * 204 * @since 14 205 */ 206 RELEASE_14; 207 208 // Note that when adding constants for newer releases, the 209 // behavior of latest() and latestSupported() must be updated too. 210 211 /** 212 * Returns the latest source version that can be modeled. 213 * 214 * @return the latest source version that can be modeled 215 */ 216 public static SourceVersion latest() { 217 return RELEASE_14; 218 } 219 220 private static final SourceVersion latestSupported = getLatestSupported(); 221 222 /* 223 * The integer version to enum constant mapping implemented by 224 * this method assumes the JEP 322: "Time-Based Release 225 * Versioning" scheme is in effect. This scheme began in JDK 226 * 10. If the JDK versioning scheme is revised, this method may 227 * need to be updated accordingly. 228 */ 229 private static SourceVersion getLatestSupported() { 230 int intVersion = Runtime.version().feature(); 231 return (intVersion >= 11) ? 232 valueOf("RELEASE_" + Math.min(14, intVersion)): 233 RELEASE_10; 234 } 235 236 /** 237 * Returns the latest source version fully supported by the 238 * current execution environment. {@code RELEASE_9} or later must 239 * be returned. 240 * 241 * @apiNote This method is included alongside {@link latest} to 242 * allow identification of situations where the language model API 243 * is running on a platform version different than the latest 244 * version modeled by the API. One way that sort of situation can 245 * occur is if an IDE or similar tool is using the API to model 246 * source version <i>N</i> while running on platform version 247 * (<i>N</i> - 1). Running in this configuration is 248 * supported by the API. Running an API on platform versions 249 * earlier than (<i>N</i> - 1) or later than <i>N</i> 250 * may or may not work as an implementation detail. If an 251 * annotation processor was generating code to run under the 252 * current execution environment, the processor should only use 253 * platform features up to the {@code latestSupported} release, 254 * which may be earlier than the {@code latest} release. 255 * 256 * @return the latest source version that is fully supported 257 */ 258 public static SourceVersion latestSupported() { 259 return latestSupported; 260 } 261 262 /** 263 * Returns whether or not {@code name} is a syntactically valid 264 * identifier (simple name) or keyword in the latest source 265 * version. The method returns {@code true} if the name consists 266 * of an initial character for which {@link 267 * Character#isJavaIdentifierStart(int)} returns {@code true}, 268 * followed only by characters for which {@link 269 * Character#isJavaIdentifierPart(int)} returns {@code true}. 270 * This pattern matches regular identifiers, keywords, restricted 271 * keywords, restricted identifiers and the literals {@code "true"}, 272 * {@code "false"}, {@code "null"}. 273 * 274 * The method returns {@code false} for all other strings. 275 * 276 * @param name the string to check 277 * @return {@code true} if this string is a 278 * syntactically valid identifier or keyword, {@code false} 279 * otherwise. 280 */ 281 public static boolean isIdentifier(CharSequence name) { 282 String id = name.toString(); 283 284 if (id.length() == 0) { 285 return false; 286 } 287 int cp = id.codePointAt(0); 288 if (!Character.isJavaIdentifierStart(cp)) { 289 return false; 290 } 291 for (int i = Character.charCount(cp); 292 i < id.length(); 293 i += Character.charCount(cp)) { 294 cp = id.codePointAt(i); 295 if (!Character.isJavaIdentifierPart(cp)) { 296 return false; 297 } 298 } 299 return true; 300 } 301 302 /** 303 * Returns whether or not {@code name} is a syntactically valid 304 * qualified name in the latest source version. Unlike {@link 305 * #isIdentifier isIdentifier}, this method returns {@code false} 306 * for keywords, boolean literals, and the null literal. 307 * 308 * This method returns {@code true} for <i>restricted 309 * keywords</i> and <i>restricted identifiers</i> 310 * 311 * @param name the string to check 312 * @return {@code true} if this string is a 313 * syntactically valid name, {@code false} otherwise. 314 * @jls 3.9 Keywords 315 * @jls 6.2 Names and Identifiers 316 */ 317 public static boolean isName(CharSequence name) { 318 return isName(name, latest()); 319 } 320 321 /** 322 * Returns whether or not {@code name} is a syntactically valid 323 * qualified name in the given source version. Unlike {@link 324 * #isIdentifier isIdentifier}, this method returns {@code false} 325 * for keywords, boolean literals, and the null literal. 326 * 327 * This method returns {@code true} for <i>restricted 328 * keywords</i> and <i>restricted identifiers</i> 329 * 330 * @param name the string to check 331 * @param version the version to use 332 * @return {@code true} if this string is a 333 * syntactically valid name, {@code false} otherwise. 334 * @jls 3.9 Keywords 335 * @jls 6.2 Names and Identifiers 336 * @since 9 337 */ 338 public static boolean isName(CharSequence name, SourceVersion version) { 339 String id = name.toString(); 340 341 for(String s : id.split("\\.", -1)) { 342 if (!isIdentifier(s) || isKeyword(s, version)) 343 return false; 344 } 345 return true; 346 } 347 348 /** 349 * Returns whether or not {@code s} is a keyword, boolean literal, 350 * or null literal in the latest source version. 351 * This method returns {@code false} for <i>restricted 352 * keywords</i> and <i>restricted identifiers</i>. 353 * 354 * @param s the string to check 355 * @return {@code true} if {@code s} is a keyword, or boolean 356 * literal, or null literal, {@code false} otherwise. 357 * @jls 3.9 Keywords 358 * @jls 3.10.3 Boolean Literals 359 * @jls 3.10.7 The Null Literal 360 */ 361 public static boolean isKeyword(CharSequence s) { 362 return isKeyword(s, latest()); 363 } 364 365 /** 366 * Returns whether or not {@code s} is a keyword, boolean literal, 367 * or null literal in the given source version. 368 * This method returns {@code false} for <i>restricted 369 * keywords</i> and <i>restricted identifiers</i>. 370 * 371 * @param s the string to check 372 * @param version the version to use 373 * @return {@code true} if {@code s} is a keyword, or boolean 374 * literal, or null literal, {@code false} otherwise. 375 * @jls 3.9 Keywords 376 * @jls 3.10.3 Boolean Literals 377 * @jls 3.10.7 The Null Literal 378 * @since 9 379 */ 380 public static boolean isKeyword(CharSequence s, SourceVersion version) { 381 String id = s.toString(); 382 switch(id) { 383 // A trip through history 384 case "strictfp": 385 return version.compareTo(RELEASE_2) >= 0; 386 387 case "assert": 388 return version.compareTo(RELEASE_4) >= 0; 389 390 case "enum": 391 return version.compareTo(RELEASE_5) >= 0; 392 393 case "_": 394 return version.compareTo(RELEASE_9) >= 0; 395 396 // Keywords common across versions 397 398 // Modifiers 399 case "public": case "protected": case "private": 400 case "abstract": case "static": case "final": 401 case "transient": case "volatile": case "synchronized": 402 case "native": 403 404 // Declarations 405 case "class": case "interface": case "extends": 406 case "package": case "throws": case "implements": 407 408 // Primitive types and void 409 case "boolean": case "byte": case "char": 410 case "short": case "int": case "long": 411 case "float": case "double": 412 case "void": 413 414 // Control flow 415 case "if": case "else": 416 case "try": case "catch": case "finally": 417 case "do": case "while": 418 case "for": case "continue": 419 case "switch": case "case": case "default": 420 case "break": case "throw": case "return": 421 422 // Other keywords 423 case "this": case "new": case "super": 424 case "import": case "instanceof": 425 426 // Forbidden! 427 case "goto": case "const": 428 429 // literals 430 case "null": case "true": case "false": 431 return true; 432 433 default: 434 return false; 435 } 436 } 437 }