1 /* 2 * Copyright (c) 2005, 2015, 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 * 1.9: To be determined 59 */ 60 61 /** 62 * The original version. 63 * 64 * The language described in 65 * <cite>The Java™ Language Specification, First Edition</cite>. 66 */ 67 RELEASE_0, 68 69 /** 70 * The version recognized by the Java Platform 1.1. 71 * 72 * The language is {@code RELEASE_0} augmented with nested classes as described in the 1.1 update to 73 * <cite>The Java™ Language Specification, First Edition</cite>. 74 */ 75 RELEASE_1, 76 77 /** 78 * The version recognized by the Java 2 Platform, Standard Edition, 79 * v 1.2. 80 * 81 * The language described in 82 * <cite>The Java™ Language Specification, 83 * Second Edition</cite>, which includes the {@code 84 * strictfp} modifier. 85 */ 86 RELEASE_2, 87 88 /** 89 * The version recognized by the Java 2 Platform, Standard Edition, 90 * v 1.3. 91 * 92 * No major changes from {@code RELEASE_2}. 93 */ 94 RELEASE_3, 95 96 /** 97 * The version recognized by the Java 2 Platform, Standard Edition, 98 * v 1.4. 99 * 100 * Added a simple assertion facility. 101 */ 102 RELEASE_4, 103 104 /** 105 * The version recognized by the Java 2 Platform, Standard 106 * Edition 5.0. 107 * 108 * The language described in 109 * <cite>The Java™ Language Specification, 110 * Third Edition</cite>. First release to support 111 * generics, annotations, autoboxing, var-args, enhanced {@code 112 * for} loop, and hexadecimal floating-point literals. 113 */ 114 RELEASE_5, 115 116 /** 117 * The version recognized by the Java Platform, Standard Edition 118 * 6. 119 * 120 * No major changes from {@code RELEASE_5}. 121 */ 122 RELEASE_6, 123 124 /** 125 * The version recognized by the Java Platform, Standard Edition 126 * 7. 127 * 128 * Additions in this release include, diamond syntax for 129 * constructors, {@code try}-with-resources, strings in switch, 130 * binary literals, and multi-catch. 131 * @since 1.7 132 */ 133 RELEASE_7, 134 135 /** 136 * The version recognized by the Java Platform, Standard Edition 137 * 8. 138 * 139 * Additions in this release include lambda expressions and default methods. 140 * @since 1.8 141 */ 142 RELEASE_8, 143 144 /** 145 * The version recognized by the Java Platform, Standard Edition 146 * 9. 147 * 148 * @since 9 149 */ 150 RELEASE_9; 151 152 // Note that when adding constants for newer releases, the 153 // behavior of latest() and latestSupported() must be updated too. 154 155 /** 156 * Returns the latest source version that can be modeled. 157 * 158 * @return the latest source version that can be modeled 159 */ 160 public static SourceVersion latest() { 161 return RELEASE_9; 162 } 163 164 private static final SourceVersion latestSupported = getLatestSupported(); 165 166 private static SourceVersion getLatestSupported() { 167 try { 168 String specVersion = System.getProperty("java.specification.version"); 169 170 switch (specVersion) { 171 case "9": 172 case "1.9": 173 return RELEASE_9; 174 case "1.8": 175 return RELEASE_8; 176 case "1.7": 177 return RELEASE_7; 178 case "1.6": 179 return RELEASE_6; 180 } 181 } catch (SecurityException se) {} 182 183 return RELEASE_5; 184 } 185 186 /** 187 * Returns the latest source version fully supported by the 188 * current execution environment. {@code RELEASE_5} or later must 189 * be returned. 190 * 191 * @return the latest source version that is fully supported 192 */ 193 public static SourceVersion latestSupported() { 194 return latestSupported; 195 } 196 197 /** 198 * Returns whether or not {@code name} is a syntactically valid 199 * identifier (simple name) or keyword in the latest source 200 * version. The method returns {@code true} if the name consists 201 * of an initial character for which {@link 202 * Character#isJavaIdentifierStart(int)} returns {@code true}, 203 * followed only by characters for which {@link 204 * Character#isJavaIdentifierPart(int)} returns {@code true}. 205 * This pattern matches regular identifiers, keywords, and the 206 * literals {@code "true"}, {@code "false"}, and {@code "null"}. 207 * The method returns {@code false} for all other strings. 208 * 209 * @param name the string to check 210 * @return {@code true} if this string is a 211 * syntactically valid identifier or keyword, {@code false} 212 * otherwise. 213 */ 214 public static boolean isIdentifier(CharSequence name) { 215 String id = name.toString(); 216 217 if (id.length() == 0) { 218 return false; 219 } 220 int cp = id.codePointAt(0); 221 if (!Character.isJavaIdentifierStart(cp)) { 222 return false; 223 } 224 for (int i = Character.charCount(cp); 225 i < id.length(); 226 i += Character.charCount(cp)) { 227 cp = id.codePointAt(i); 228 if (!Character.isJavaIdentifierPart(cp)) { 229 return false; 230 } 231 } 232 return true; 233 } 234 235 /** 236 * Returns whether or not {@code name} is a syntactically valid 237 * qualified name in the latest source version. Unlike {@link 238 * #isIdentifier isIdentifier}, this method returns {@code false} 239 * for keywords and literals. 240 * 241 * @param name the string to check 242 * @return {@code true} if this string is a 243 * syntactically valid name, {@code false} otherwise. 244 * @jls 6.2 Names and Identifiers 245 */ 246 public static boolean isName(CharSequence name) { 247 String id = name.toString(); 248 249 for(String s : id.split("\\.", -1)) { 250 if (!isIdentifier(s) || isKeyword(s)) 251 return false; 252 } 253 return true; 254 } 255 256 private final static Set<String> keywords; 257 static { 258 Set<String> s = new HashSet<>(); 259 String [] kws = { 260 "abstract", "continue", "for", "new", "switch", 261 "assert", "default", "if", "package", "synchronized", 262 "boolean", "do", "goto", "private", "this", 263 "break", "double", "implements", "protected", "throw", 264 "byte", "else", "import", "public", "throws", 265 "case", "enum", "instanceof", "return", "transient", 266 "catch", "extends", "int", "short", "try", 267 "char", "final", "interface", "static", "void", 268 "class", "finally", "long", "strictfp", "volatile", 269 "const", "float", "native", "super", "while", 270 // literals 271 "null", "true", "false" 272 }; 273 for(String kw : kws) 274 s.add(kw); 275 keywords = Collections.unmodifiableSet(s); 276 } 277 278 /** 279 * Returns whether or not {@code s} is a keyword or literal in the 280 * latest source version. 281 * 282 * @param s the string to check 283 * @return {@code true} if {@code s} is a keyword or literal, {@code false} otherwise. 284 */ 285 public static boolean isKeyword(CharSequence s) { 286 return keywords.contains(s.toString()); 287 } 288 }