1 /* 2 * Copyright (c) 2005, 2013, 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 1.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 "1.9": 172 return RELEASE_9; 173 case "1.8": 174 return RELEASE_8; 175 case "1.7": 176 return RELEASE_7; 177 case "1.6": 178 return RELEASE_6; 179 } 180 } catch (SecurityException se) {} 181 182 return RELEASE_5; 183 } 184 185 /** 186 * Returns the latest source version fully supported by the 187 * current execution environment. {@code RELEASE_5} or later must 188 * be returned. 189 * 190 * @return the latest source version that is fully supported 191 */ 192 public static SourceVersion latestSupported() { 193 return latestSupported; 194 } 195 196 /** 197 * Returns whether or not {@code name} is a syntactically valid 198 * identifier (simple name) or keyword in the latest source 199 * version. The method returns {@code true} if the name consists 200 * of an initial character for which {@link 201 * Character#isJavaIdentifierStart(int)} returns {@code true}, 202 * followed only by characters for which {@link 203 * Character#isJavaIdentifierPart(int)} returns {@code true}. 204 * This pattern matches regular identifiers, keywords, and the 205 * literals {@code "true"}, {@code "false"}, and {@code "null"}. 206 * The method returns {@code false} for all other strings. 207 * 208 * @param name the string to check 209 * @return {@code true} if this string is a 210 * syntactically valid identifier or keyword, {@code false} 211 * otherwise. 212 */ 213 public static boolean isIdentifier(CharSequence name) { 214 String id = name.toString(); 215 216 if (id.length() == 0) { 217 return false; 218 } 219 int cp = id.codePointAt(0); 220 if (!Character.isJavaIdentifierStart(cp)) { 221 return false; 222 } 223 for (int i = Character.charCount(cp); 224 i < id.length(); 225 i += Character.charCount(cp)) { 226 cp = id.codePointAt(i); 227 if (!Character.isJavaIdentifierPart(cp)) { 228 return false; 229 } 230 } 231 return true; 232 } 233 234 /** 235 * Returns whether or not {@code name} is a syntactically valid 236 * qualified name in the latest source version. Unlike {@link 237 * #isIdentifier isIdentifier}, this method returns {@code false} 238 * for keywords and literals. 239 * 240 * @param name the string to check 241 * @return {@code true} if this string is a 242 * syntactically valid name, {@code false} otherwise. 243 * @jls 6.2 Names and Identifiers 244 */ 245 public static boolean isName(CharSequence name) { 246 String id = name.toString(); 247 248 for(String s : id.split("\\.", -1)) { 249 if (!isIdentifier(s) || isKeyword(s)) 250 return false; 251 } 252 return true; 253 } 254 255 private final static Set<String> keywords; 256 static { 257 Set<String> s = new HashSet<>(); 258 String [] kws = { 259 "abstract", "continue", "for", "new", "switch", 260 "assert", "default", "if", "package", "synchronized", 261 "boolean", "do", "goto", "private", "this", 262 "break", "double", "implements", "protected", "throw", 263 "byte", "else", "import", "public", "throws", 264 "case", "enum", "instanceof", "return", "transient", 265 "catch", "extends", "int", "short", "try", 266 "char", "final", "interface", "static", "void", 267 "class", "finally", "long", "strictfp", "volatile", 268 "const", "float", "native", "super", "while", 269 // literals 270 "null", "true", "false" 271 }; 272 for(String kw : kws) 273 s.add(kw); 274 keywords = Collections.unmodifiableSet(s); 275 } 276 277 /** 278 * Returns whether or not {@code s} is a keyword or literal in the 279 * latest source version. 280 * 281 * @param s the string to check 282 * @return {@code true} if {@code s} is a keyword or literal, {@code false} otherwise. 283 */ 284 public static boolean isKeyword(CharSequence s) { 285 return keywords.contains(s.toString()); 286 } 287 }