SourceVersion.java revision 3119:89ba2a17ce41
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
26package javax.lang.model;
27
28import java.util.Collections;
29import java.util.Set;
30import java.util.HashSet;
31
32/**
33 * Source versions of the Java™ programming language.
34 *
35 * See the appropriate edition of
36 * <cite>The Java&trade; 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&eacute;
45 * @since 1.6
46 */
47public 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&trade; 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&trade; 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&trade; 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&trade; 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 "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}
289