SourceVersion.java revision 2571:10fc81ac75b4
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
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 "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}
288