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