--- old/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java 2016-05-17 15:05:49.936944937 -0700 +++ new/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java 2016-05-17 15:05:49.772944940 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,7 +55,7 @@ * 1.6: no changes * 1.7: diamond syntax, try-with-resources, etc. * 1.8: lambda expressions and default methods - * 9: To be determined + * 9: modules, small cleanups to 1.7 and 1.8 changes */ /** @@ -145,6 +145,9 @@ * The version recognized by the Java Platform, Standard Edition * 9. * + * Additions in this release include modules and removal of a + * single underscore from the set of legal identifier names. + * * @since 9 */ RELEASE_9; @@ -233,10 +236,10 @@ } /** - * Returns whether or not {@code name} is a syntactically valid - * qualified name in the latest source version. Unlike {@link - * #isIdentifier isIdentifier}, this method returns {@code false} - * for keywords and literals. + * Returns whether or not {@code name} is a syntactically valid + * qualified name in the latest source version. Unlike {@link + * #isIdentifier isIdentifier}, this method returns {@code false} + * for keywords and literals. * * @param name the string to check * @return {@code true} if this string is a @@ -244,45 +247,87 @@ * @jls 6.2 Names and Identifiers */ public static boolean isName(CharSequence name) { + return isName(name, latest()); + } + + /** + * Returns whether or not {@code name} is a syntactically valid + * qualified name in the given source version. Unlike {@link + * #isIdentifier isIdentifier}, this method returns {@code false} + * for keywords and literals. + * + * @param name the string to check + * @param version the version to use + * @return {@code true} if this string is a + * syntactically valid name, {@code false} otherwise. + * @jls 6.2 Names and Identifiers + * @since 9 + */ + public static boolean isName(CharSequence name, SourceVersion version) { String id = name.toString(); for(String s : id.split("\\.", -1)) { - if (!isIdentifier(s) || isKeyword(s)) + if (!isIdentifier(s) || isKeyword(s, version)) return false; } return true; } - private final static Set keywords; - static { - Set s = new HashSet<>(); - String [] kws = { - "abstract", "continue", "for", "new", "switch", - "assert", "default", "if", "package", "synchronized", - "boolean", "do", "goto", "private", "this", - "break", "double", "implements", "protected", "throw", - "byte", "else", "import", "public", "throws", - "case", "enum", "instanceof", "return", "transient", - "catch", "extends", "int", "short", "try", - "char", "final", "interface", "static", "void", - "class", "finally", "long", "strictfp", "volatile", - "const", "float", "native", "super", "while", - // literals - "null", "true", "false" - }; - for(String kw : kws) - s.add(kw); - keywords = Collections.unmodifiableSet(s); + /** + * Returns whether or not {@code s} is a keyword or literal in the + * latest source version. + * + * @param s the string to check + * @return {@code true} if {@code s} is a keyword or literal, {@code false} otherwise. + */ + public static boolean isKeyword(CharSequence s) { + return isKeyword(s, latest()); } /** - * Returns whether or not {@code s} is a keyword or literal in the - * latest source version. + * Returns whether or not {@code s} is a keyword or literal in the + * given source version. * * @param s the string to check + * @param version the version to use * @return {@code true} if {@code s} is a keyword or literal, {@code false} otherwise. + * @since 9 */ - public static boolean isKeyword(CharSequence s) { - return keywords.contains(s.toString()); + public static boolean isKeyword(CharSequence s, SourceVersion version) { + String id = s.toString(); + switch(id) { + // A trip through history + case "strictfp": + return version.compareTo(RELEASE_2) >= 0; + + case "assert": + return version.compareTo(RELEASE_4) >= 0; + + case "enum": + return version.compareTo(RELEASE_5) >= 0; + + case "_": + return version.compareTo(RELEASE_9) >= 0; + + // Keywords common across versions + case "abstract": case "continue": case "for": case "new": + case "switch": case "default": case "if": case "package": + case "synchronized": case "boolean": case "do": case "goto": + case "private": case "this": case "break": case "double": + case "implements": case "protected": case "throw": case "byte": + case "else": case "import": case "public": case "throws": + case "case": case "instanceof": case "return": case "transient": + case "catch": case "extends": case "int": case "short": + case "try": case "char": case "final": case "interface": + case "static": case "void": case "class": case "finally": + case "long": case "volatile": case "const": case "float": + case "native": case "super": case "while": + // literals + case "null": case "true": case "false": + return true; + + default: + return false; + } } }