SourceVersion.java revision 3423:d6224976006a
168651Skris/* 268651Skris * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. 368651Skris * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 468651Skris * 568651Skris * This code is free software; you can redistribute it and/or modify it 668651Skris * under the terms of the GNU General Public License version 2 only, as 768651Skris * published by the Free Software Foundation. Oracle designates this 868651Skris * particular file as subject to the "Classpath" exception as provided 968651Skris * by Oracle in the LICENSE file that accompanied this code. 1068651Skris * 1168651Skris * This code is distributed in the hope that it will be useful, but WITHOUT 1268651Skris * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1368651Skris * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1468651Skris * version 2 for more details (a copy is included in the LICENSE file that 1568651Skris * accompanied this code). 1668651Skris * 1768651Skris * You should have received a copy of the GNU General Public License version 18109998Smarkm * 2 along with this work; if not, write to the Free Software Foundation, 1968651Skris * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2068651Skris * 2168651Skris * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2268651Skris * or visit www.oracle.com if you need additional information or have any 2368651Skris * questions. 2468651Skris */ 25109998Smarkm 2668651Skrispackage javax.lang.model; 2768651Skris 28109998Smarkmimport java.util.Collections; 2968651Skrisimport java.util.Set; 30109998Smarkmimport java.util.HashSet; 3168651Skris 3268651Skris/** 33109998Smarkm * Source versions of the Java™ programming language. 3468651Skris * 3568651Skris * See the appropriate edition of 36109998Smarkm * <cite>The Java™ Language Specification</cite> 3768651Skris * for information about a particular source version. 38109998Smarkm * 39109998Smarkm * <p>Note that additional source version constants will be added to 4068651Skris * model future releases of the language. 4168651Skris * 4268651Skris * @author Joseph D. Darcy 4368651Skris * @author Scott Seligman 4468651Skris * @author Peter von der Ahé 4568651Skris * @since 1.6 4668651Skris */ 4768651Skrispublic enum SourceVersion { 4868651Skris /* 4968651Skris * Summary of language evolution 5068651Skris * 1.1: nested classes 5168651Skris * 1.2: strictfp 5268651Skris * 1.3: no changes 5368651Skris * 1.4: assert 5468651Skris * 1.5: annotations, generics, autoboxing, var-args... 55109998Smarkm * 1.6: no changes 5668651Skris * 1.7: diamond syntax, try-with-resources, etc. 57109998Smarkm * 1.8: lambda expressions and default methods 58109998Smarkm * 9: modules, small cleanups to 1.7 and 1.8 changes 5968651Skris */ 6068651Skris 6168651Skris /** 6268651Skris * The original version. 6368651Skris * 6468651Skris * The language described in 6568651Skris * <cite>The Java™ Language Specification, First Edition</cite>. 6668651Skris */ 6768651Skris RELEASE_0, 6868651Skris 6968651Skris /** 7068651Skris * The version recognized by the Java Platform 1.1. 7168651Skris * 7268651Skris * The language is {@code RELEASE_0} augmented with nested classes as described in the 1.1 update to 7368651Skris * <cite>The Java™ Language Specification, First Edition</cite>. 7468651Skris */ 7568651Skris RELEASE_1, 7668651Skris 7768651Skris /** 7868651Skris * The version recognized by the Java 2 Platform, Standard Edition, 7968651Skris * v 1.2. 8068651Skris * 8168651Skris * The language described in 8268651Skris * <cite>The Java™ Language Specification, 8368651Skris * Second Edition</cite>, which includes the {@code 8468651Skris * strictfp} modifier. 8568651Skris */ 8668651Skris RELEASE_2, 8768651Skris 8868651Skris /** 8968651Skris * The version recognized by the Java 2 Platform, Standard Edition, 9068651Skris * v 1.3. 9168651Skris * 9268651Skris * No major changes from {@code RELEASE_2}. 9368651Skris */ 9468651Skris RELEASE_3, 95109998Smarkm 9668651Skris /** 9768651Skris * The version recognized by the Java 2 Platform, Standard Edition, 9868651Skris * v 1.4. 9968651Skris * 10068651Skris * Added a simple assertion facility. 10168651Skris */ 10268651Skris RELEASE_4, 10368651Skris 10468651Skris /** 10568651Skris * The version recognized by the Java 2 Platform, Standard 10668651Skris * Edition 5.0. 10768651Skris * 10868651Skris * The language described in 10968651Skris * <cite>The Java™ Language Specification, 11068651Skris * Third Edition</cite>. First release to support 11168651Skris * generics, annotations, autoboxing, var-args, enhanced {@code 11268651Skris * for} loop, and hexadecimal floating-point literals. 11368651Skris */ 11468651Skris RELEASE_5, 11568651Skris 11668651Skris /** 11768651Skris * The version recognized by the Java Platform, Standard Edition 11868651Skris * 6. 11968651Skris * 12068651Skris * No major changes from {@code RELEASE_5}. 12168651Skris */ 12268651Skris RELEASE_6, 12368651Skris 12468651Skris /** 12568651Skris * The version recognized by the Java Platform, Standard Edition 12668651Skris * 7. 12768651Skris * 12868651Skris * Additions in this release include, diamond syntax for 12968651Skris * constructors, {@code try}-with-resources, strings in switch, 13068651Skris * binary literals, and multi-catch. 13168651Skris * @since 1.7 13268651Skris */ 133109998Smarkm RELEASE_7, 13468651Skris 13568651Skris /** 13668651Skris * The version recognized by the Java Platform, Standard Edition 13768651Skris * 8. 13868651Skris * 13968651Skris * Additions in this release include lambda expressions and default methods. 14068651Skris * @since 1.8 14168651Skris */ 14268651Skris RELEASE_8, 14368651Skris 14468651Skris /** 14568651Skris * The version recognized by the Java Platform, Standard Edition 14668651Skris * 9. 14768651Skris * 14868651Skris * Additions in this release include modules and removal of a 14968651Skris * single underscore from the set of legal identifier names. 15068651Skris * 15168651Skris * @since 9 15268651Skris */ 15368651Skris RELEASE_9; 15468651Skris 15568651Skris // Note that when adding constants for newer releases, the 15668651Skris // behavior of latest() and latestSupported() must be updated too. 15768651Skris 15868651Skris /** 15968651Skris * Returns the latest source version that can be modeled. 16068651Skris * 16168651Skris * @return the latest source version that can be modeled 16268651Skris */ 16368651Skris public static SourceVersion latest() { 16468651Skris return RELEASE_9; 16568651Skris } 16668651Skris 16768651Skris private static final SourceVersion latestSupported = getLatestSupported(); 16868651Skris 16968651Skris private static SourceVersion getLatestSupported() { 17068651Skris try { 17168651Skris String specVersion = System.getProperty("java.specification.version"); 17268651Skris 17368651Skris switch (specVersion) { 17468651Skris case "9": 17568651Skris case "1.9": 17668651Skris return RELEASE_9; 17768651Skris case "1.8": 17868651Skris return RELEASE_8; 17968651Skris case "1.7": 18068651Skris return RELEASE_7; 18168651Skris case "1.6": 18268651Skris return RELEASE_6; 18368651Skris } 18468651Skris } catch (SecurityException se) {} 18568651Skris 18668651Skris return RELEASE_5; 18768651Skris } 18868651Skris 18968651Skris /** 19068651Skris * Returns the latest source version fully supported by the 19168651Skris * current execution environment. {@code RELEASE_5} or later must 19268651Skris * be returned. 19368651Skris * 19468651Skris * @return the latest source version that is fully supported 19568651Skris */ 19668651Skris public static SourceVersion latestSupported() { 19768651Skris return latestSupported; 19868651Skris } 199109998Smarkm 200109998Smarkm /** 20168651Skris * Returns whether or not {@code name} is a syntactically valid 20268651Skris * identifier (simple name) or keyword in the latest source 20368651Skris * version. The method returns {@code true} if the name consists 20468651Skris * of an initial character for which {@link 20568651Skris * Character#isJavaIdentifierStart(int)} returns {@code true}, 206109998Smarkm * followed only by characters for which {@link 20768651Skris * Character#isJavaIdentifierPart(int)} returns {@code true}. 20868651Skris * This pattern matches regular identifiers, keywords, and the 20968651Skris * literals {@code "true"}, {@code "false"}, and {@code "null"}. 21068651Skris * The method returns {@code false} for all other strings. 21168651Skris * 212109998Smarkm * @param name the string to check 21368651Skris * @return {@code true} if this string is a 21468651Skris * syntactically valid identifier or keyword, {@code false} 21568651Skris * otherwise. 21668651Skris */ 21768651Skris public static boolean isIdentifier(CharSequence name) { 218109998Smarkm String id = name.toString(); 21968651Skris 22068651Skris if (id.length() == 0) { 22168651Skris return false; 222109998Smarkm } 22368651Skris int cp = id.codePointAt(0); 22468651Skris if (!Character.isJavaIdentifierStart(cp)) { 22568651Skris return false; 22668651Skris } 22768651Skris for (int i = Character.charCount(cp); 22868651Skris i < id.length(); 22968651Skris i += Character.charCount(cp)) { 23068651Skris cp = id.codePointAt(i); 23168651Skris if (!Character.isJavaIdentifierPart(cp)) { 23268651Skris return false; 23368651Skris } 23468651Skris } 23568651Skris return true; 23668651Skris } 23768651Skris 23868651Skris /** 23968651Skris * Returns whether or not {@code name} is a syntactically valid 24068651Skris * qualified name in the latest source version. Unlike {@link 24168651Skris * #isIdentifier isIdentifier}, this method returns {@code false} 242109998Smarkm * for keywords, boolean literals, and the null literal. 24368651Skris * 24468651Skris * @param name the string to check 24568651Skris * @return {@code true} if this string is a 24668651Skris * syntactically valid name, {@code false} otherwise. 24768651Skris * @jls 6.2 Names and Identifiers 24868651Skris */ 24968651Skris public static boolean isName(CharSequence name) { 25068651Skris return isName(name, latest()); 25168651Skris } 25268651Skris 25368651Skris /** 25468651Skris * Returns whether or not {@code name} is a syntactically valid 25568651Skris * qualified name in the given source version. Unlike {@link 25668651Skris * #isIdentifier isIdentifier}, this method returns {@code false} 25768651Skris * for keywords, boolean literals, and the null literal. 25868651Skris * 25968651Skris * @param name the string to check 26068651Skris * @param version the version to use 26168651Skris * @return {@code true} if this string is a 26268651Skris * syntactically valid name, {@code false} otherwise. 26368651Skris * @jls 6.2 Names and Identifiers 26468651Skris * @since 9 26568651Skris */ 26668651Skris public static boolean isName(CharSequence name, SourceVersion version) { 26768651Skris String id = name.toString(); 26868651Skris 26968651Skris for(String s : id.split("\\.", -1)) { 27068651Skris if (!isIdentifier(s) || isKeyword(s, version)) 27168651Skris return false; 27268651Skris } 27368651Skris return true; 27468651Skris } 27568651Skris 27668651Skris /** 27768651Skris * Returns whether or not {@code s} is a keyword, boolean literal, 27868651Skris * or null literal in the latest source version. 27968651Skris * 28068651Skris * @param s the string to check 28168651Skris * @return {@code true} if {@code s} is a keyword, or boolean 28268651Skris * literal, or null literal, {@code false} otherwise. 28368651Skris * @jls 3.9 Keywords 28468651Skris * @jls 3.10.3 Boolean Literals 28568651Skris * @jls 3.10.7 The Null Literal 28668651Skris */ 28768651Skris public static boolean isKeyword(CharSequence s) { 28868651Skris return isKeyword(s, latest()); 28968651Skris } 29068651Skris 29168651Skris /** 29268651Skris * Returns whether or not {@code s} is a keyword, boolean literal, 29368651Skris * or null literal in the given source version. 29468651Skris * 29568651Skris * @param s the string to check 29668651Skris * @param version the version to use 29768651Skris * @return {@code true} if {@code s} is a keyword, or boolean 29868651Skris * literal, or null literal, {@code false} otherwise. 29968651Skris * @jls 3.9 Keywords 30068651Skris * @jls 3.10.3 Boolean Literals 30168651Skris * @jls 3.10.7 The Null Literal 30268651Skris * @since 9 30368651Skris */ 304109998Smarkm public static boolean isKeyword(CharSequence s, SourceVersion version) { 305109998Smarkm String id = s.toString(); 30668651Skris switch(id) { 30768651Skris // A trip through history 30868651Skris case "strictfp": 30968651Skris return version.compareTo(RELEASE_2) >= 0; 31068651Skris 31168651Skris case "assert": 31268651Skris return version.compareTo(RELEASE_4) >= 0; 31368651Skris 31468651Skris case "enum": 31568651Skris return version.compareTo(RELEASE_5) >= 0; 31668651Skris 31768651Skris case "_": 31868651Skris return version.compareTo(RELEASE_9) >= 0; 31968651Skris 32068651Skris // Keywords common across versions 32168651Skris 32268651Skris // Modifiers 32368651Skris case "public": case "protected": case "private": 32468651Skris case "abstract": case "static": case "final": 32568651Skris case "transient": case "volatile": case "synchronized": 32668651Skris case "native": 32768651Skris 32868651Skris // Declarations 32968651Skris case "class": case "interface": case "extends": 33068651Skris case "package": case "throws": case "implements": 33168651Skris 33268651Skris // Primitive types and void 33368651Skris case "boolean": case "byte": case "char": 33468651Skris case "short": case "int": case "long": 33568651Skris case "float": case "double": 33668651Skris case "void": 33768651Skris 33868651Skris // Control flow 33968651Skris case "if": case "else": 34068651Skris case "try": case "catch": case "finally": 34168651Skris case "do": case "while": 34268651Skris case "for": case "continue": 343109998Smarkm case "switch": case "case": case "default": 344109998Smarkm case "break": case "throw": case "return": 34568651Skris 34668651Skris // Other keywords 34768651Skris case "this": case "new": case "super": 34868651Skris case "import": case "instanceof": 34968651Skris 35068651Skris // Forbidden! 35168651Skris case "goto": case "const": 35268651Skris 35368651Skris // literals 35468651Skris case "null": case "true": case "false": 35568651Skris return true; 35668651Skris 35768651Skris default: 35868651Skris return false; 35968651Skris } 360109998Smarkm } 36168651Skris} 362109998Smarkm