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