8189749: Devise strategy for making source level checks more uniform
authormcimadamore
Mon, 04 Dec 2017 17:54:49 +0000
changeset 48054 702043a4cdeb
parent 48053 6dcbdc9f99fc
child 48055 14cd5bd01d81
8189749: Devise strategy for making source level checks more uniform Summary: Create a 'feature' enum which is responsible for handling source version checks and related diagnostic generation Reviewed-by: jjg, jlahoda
src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java
src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java
src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java
src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Analyzer.java
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java
src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java
src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java
src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java
src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java
src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/RootDocImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java
src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java
src/jdk.jshell/share/classes/jdk/jshell/ReplParser.java
test/langtools/jdk/jshell/CompilerOptionsTest.java
test/langtools/tools/javac/StringsInSwitch/BadlyTypedLabel1_6.out
test/langtools/tools/javac/StringsInSwitch/BadlyTypedLabel2_6.out
test/langtools/tools/javac/StringsInSwitch/NonConstantLabel6.out
test/langtools/tools/javac/StringsInSwitch/OneCaseSwitches.out
test/langtools/tools/javac/StringsInSwitch/RSCL1_6.out
test/langtools/tools/javac/StringsInSwitch/RSCL2_6.out
test/langtools/tools/javac/TryWithResources/BadTwr6.out
test/langtools/tools/javac/TryWithResources/BadTwrSyntax6.out
test/langtools/tools/javac/TryWithResources/TwrForVariable1.out
test/langtools/tools/javac/TryWithResources/TwrOnNonResource6.out
test/langtools/tools/javac/TryWithResources/WeirdTwr.out
test/langtools/tools/javac/annotations/repeatingAnnotations/WrongVersion6.out
test/langtools/tools/javac/annotations/repeatingAnnotations/WrongVersion7.out
test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion.out
test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion7.out
test/langtools/tools/javac/annotations/typeAnnotations/failures/CheckErrorsForSource7.java
test/langtools/tools/javac/conditional/Conditional.out
test/langtools/tools/javac/defaultMethods/static/StaticInvokeQualified6.out
test/langtools/tools/javac/defaultMethods/static/StaticInvokeQualified7.out
test/langtools/tools/javac/defaultMethods/static/StaticInvokeSimple6.out
test/langtools/tools/javac/defaultMethods/static/StaticInvokeSimple7.out
test/langtools/tools/javac/depDocComment/SuppressDeprecation8.out
test/langtools/tools/javac/diags/examples.not-yet.txt
test/langtools/tools/javac/diags/examples/AnnotationsAfterTypeParamsNotSupportedInSource.java
test/langtools/tools/javac/diags/examples/DefaultMethodNotSupported.java
test/langtools/tools/javac/diags/examples/DiamondAndAnonClass.java
test/langtools/tools/javac/diags/examples/DiamondNotSupported.java
test/langtools/tools/javac/diags/examples/IntersectionTypesInCastNotSupported.java
test/langtools/tools/javac/diags/examples/LambdaNotSupported.java
test/langtools/tools/javac/diags/examples/MethodReferencesNotSupported.java
test/langtools/tools/javac/diags/examples/ModulesNotSupportedInSource/module-info.java
test/langtools/tools/javac/diags/examples/MulticatchNotSupported.java
test/langtools/tools/javac/diags/examples/PrivateInterfaceMethodsNotSupported.java
test/langtools/tools/javac/diags/examples/RepeatableAnnotationsNotSupported.java
test/langtools/tools/javac/diags/examples/StaticIntfMethodInvokeNotSupported.java
test/langtools/tools/javac/diags/examples/StaticIntfMethodNotSupported.java
test/langtools/tools/javac/diags/examples/StringSwitchNotSupported.java
test/langtools/tools/javac/diags/examples/TryResourceNotSupported.java
test/langtools/tools/javac/diags/examples/TypeAnnotationsNotSupported.java
test/langtools/tools/javac/diags/examples/UnsupportedBinaryLiteral.java
test/langtools/tools/javac/diags/examples/UnsupportedUnderscoreLiteral.java
test/langtools/tools/javac/diags/examples/VarInTryWithResourcesNotSupportedInSource.java
test/langtools/tools/javac/generics/diamond/neg/Neg09a.out
test/langtools/tools/javac/generics/diamond/neg/Neg09b.out
test/langtools/tools/javac/generics/diamond/neg/Neg09c.out
test/langtools/tools/javac/generics/diamond/neg/Neg09d.out
test/langtools/tools/javac/generics/inference/6278587/T6278587Neg.out
test/langtools/tools/javac/generics/odersky/BadTest4.out
test/langtools/tools/javac/lambda/SourceLevelTest.out
test/langtools/tools/javac/literals/BadBinaryLiterals.6.out
test/langtools/tools/javac/literals/BadUnderscoreLiterals.6.out
test/langtools/tools/javac/options/T6900037.out
test/langtools/tools/javac/parser/extend/TrialParser.java
test/langtools/tools/javac/processing/warnings/gold_sv_warn_5_6.out
test/langtools/tools/javac/varargs/6313164/T6313164Source7.out
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java	Mon Dec 04 17:54:49 2017 +0000
@@ -115,7 +115,7 @@
             values = EnumSet.noneOf(LintCategory.class);
 
             Source source = Source.instance(context);
-            if (source.compareTo(Source.JDK1_9) >= 0) {
+            if (source.compareTo(Source.JDK9) >= 0) {
                 values.add(LintCategory.DEP_ANN);
             }
             values.add(LintCategory.REQUIRES_TRANSITIVE_AUTOMATIC);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java	Mon Dec 04 17:54:49 2017 +0000
@@ -31,7 +31,12 @@
 import static javax.lang.model.SourceVersion.*;
 
 import com.sun.tools.javac.jvm.Target;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
+import com.sun.tools.javac.resources.CompilerProperties.Fragments;
 import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.util.JCDiagnostic.Error;
+import com.sun.tools.javac.util.JCDiagnostic.Fragment;
+
 import static com.sun.tools.javac.main.Option.*;
 
 /** The source language version accepted.
@@ -59,22 +64,22 @@
 
     /** 1.5 introduced generics, attributes, foreach, boxing, static import,
      *  covariant return, enums, varargs, et al. */
-    JDK1_5("1.5"),
+    JDK5("5"),
 
     /** 1.6 reports encoding problems as errors instead of warnings. */
-    JDK1_6("1.6"),
+    JDK6("6"),
 
     /** 1.7 introduced try-with-resources, multi-catch, string switch, etc. */
-    JDK1_7("1.7"),
+    JDK7("7"),
 
     /** 1.8 lambda expressions and default methods. */
-    JDK1_8("1.8"),
+    JDK8("8"),
 
     /** 1.9 modularity. */
-    JDK1_9("1.9"),
+    JDK9("9"),
 
     /** 1.10 covers the to be determined language features that will be added in JDK 10. */
-    JDK1_10("1.10");
+    JDK10("10");
 
     private static final Context.Key<Source> sourceKey = new Context.Key<>();
 
@@ -97,19 +102,19 @@
         for (Source s : values()) {
             tab.put(s.name, s);
         }
-        tab.put("5", JDK1_5); // Make 5 an alias for 1.5
-        tab.put("6", JDK1_6); // Make 6 an alias for 1.6
-        tab.put("7", JDK1_7); // Make 7 an alias for 1.7
-        tab.put("8", JDK1_8); // Make 8 an alias for 1.8
-        tab.put("9", JDK1_9); // Make 9 an alias for 1.9
-        tab.put("10", JDK1_10); // Make 10 an alias for 1.10
+        tab.put("1.5", JDK5); // Make 5 an alias for 1.5
+        tab.put("1.6", JDK6); // Make 6 an alias for 1.6
+        tab.put("1.7", JDK7); // Make 7 an alias for 1.7
+        tab.put("1.8", JDK8); // Make 8 an alias for 1.8
+        tab.put("1.9", JDK9); // Make 9 an alias for 1.9
+        tab.put("1.10", JDK10); // Make 10 an alias for 1.10
     }
 
     private Source(String name) {
         this.name = name;
     }
 
-    public static final Source MIN = Source.JDK1_6;
+    public static final Source MIN = Source.JDK6;
 
     private static final Source MAX = values()[values().length - 1];
 
@@ -120,114 +125,108 @@
     }
 
     public Target requiredTarget() {
-        if (this.compareTo(JDK1_10) >= 0) return Target.JDK1_10;
-        if (this.compareTo(JDK1_9) >= 0) return Target.JDK1_9;
-        if (this.compareTo(JDK1_8) >= 0) return Target.JDK1_8;
-        if (this.compareTo(JDK1_7) >= 0) return Target.JDK1_7;
-        if (this.compareTo(JDK1_6) >= 0) return Target.JDK1_6;
-        if (this.compareTo(JDK1_5) >= 0) return Target.JDK1_5;
+        if (this.compareTo(JDK10) >= 0) return Target.JDK1_10;
+        if (this.compareTo(JDK9) >= 0) return Target.JDK1_9;
+        if (this.compareTo(JDK8) >= 0) return Target.JDK1_8;
+        if (this.compareTo(JDK7) >= 0) return Target.JDK1_7;
+        if (this.compareTo(JDK6) >= 0) return Target.JDK1_6;
+        if (this.compareTo(JDK5) >= 0) return Target.JDK1_5;
         if (this.compareTo(JDK1_4) >= 0) return Target.JDK1_4;
         return Target.JDK1_1;
     }
 
-    public boolean allowDiamond() {
-        return compareTo(JDK1_7) >= 0;
-    }
-    public boolean allowMulticatch() {
-        return compareTo(JDK1_7) >= 0;
-    }
-    public boolean allowImprovedRethrowAnalysis() {
-        return compareTo(JDK1_7) >= 0;
-    }
-    public boolean allowImprovedCatchAnalysis() {
-        return compareTo(JDK1_7) >= 0;
-    }
-    public boolean allowModules() {
-        return compareTo(JDK1_9) >= 0;
-    }
-    public boolean allowTryWithResources() {
-        return compareTo(JDK1_7) >= 0;
-    }
-    public boolean allowEffectivelyFinalVariablesInTryWithResources() {
-        return compareTo(JDK1_9) >= 0;
-    }
-    public boolean allowBinaryLiterals() {
-        return compareTo(JDK1_7) >= 0;
-    }
-    public boolean allowUnderscoresInLiterals() {
-        return compareTo(JDK1_7) >= 0;
-    }
-    public boolean allowStringsInSwitch() {
-        return compareTo(JDK1_7) >= 0;
-    }
-    public boolean allowDeprecationOnImport() {
-        return compareTo(JDK1_9) < 0;
-    }
-    public boolean allowSimplifiedVarargs() {
-        return compareTo(JDK1_7) >= 0;
-    }
-    public boolean allowObjectToPrimitiveCast() {
-        return compareTo(JDK1_7) >= 0;
-    }
-    public boolean enforceThisDotInit() {
-        return compareTo(JDK1_7) >= 0;
-    }
-    public boolean allowPoly() {
-        return compareTo(JDK1_8) >= 0;
-    }
-    public boolean allowLambda() {
-        return compareTo(JDK1_8) >= 0;
+    /**
+     * Models a feature of the Java programming language. Each feature can be associated with a
+     * minimum source level, a maximum source level and a diagnostic fragment describing the feature,
+     * which is used to generate error messages of the kind {@code feature XYZ not supported in source N}.
+     */
+    public enum Feature {
+
+        DIAMOND(JDK7, Fragments.FeatureDiamond, DiagKind.NORMAL),
+        MULTICATCH(JDK7, Fragments.FeatureMulticatch, DiagKind.PLURAL),
+        IMPROVED_RETHROW_ANALYSIS(JDK7),
+        IMPROVED_CATCH_ANALYSIS(JDK7),
+        MODULES(JDK9, Fragments.FeatureModules, DiagKind.PLURAL),
+        TRY_WITH_RESOURCES(JDK7, Fragments.FeatureTryWithResources, DiagKind.NORMAL),
+        EFFECTIVELY_FINAL_VARIABLES_IN_TRY_WITH_RESOURCES(JDK9, Fragments.FeatureVarInTryWithResources, DiagKind.PLURAL),
+        BINARY_LITERALS(JDK7, Fragments.FeatureBinaryLit, DiagKind.PLURAL),
+        UNDERSCORES_IN_LITERALS(JDK7, Fragments.FeatureUnderscoreLit, DiagKind.PLURAL),
+        STRINGS_IN_SWITCH(JDK7, Fragments.FeatureStringSwitch, DiagKind.PLURAL),
+        DEPRECATION_ON_IMPORT(MIN, JDK9),
+        SIMPLIFIED_VARARGS(JDK7),
+        OBJECT_TO_PRIMITIVE_CAST(JDK7),
+        ENFORCE_THIS_DOT_INIT(JDK7),
+        POLY(JDK8),
+        LAMBDA(JDK8, Fragments.FeatureLambda, DiagKind.PLURAL),
+        METHOD_REFERENCES(JDK8, Fragments.FeatureMethodReferences, DiagKind.PLURAL),
+        DEFAULT_METHODS(JDK8, Fragments.FeatureDefaultMethods, DiagKind.PLURAL),
+        STATIC_INTERFACE_METHODS(JDK8, Fragments.FeatureStaticIntfMethods, DiagKind.PLURAL),
+        STATIC_INTERFACE_METHODS_INVOKE(JDK8, Fragments.FeatureStaticIntfMethodInvoke, DiagKind.PLURAL),
+        STRICT_METHOD_CLASH_CHECK(JDK8),
+        EFFECTIVELY_FINAL_IN_INNER_CLASSES(JDK8),
+        TYPE_ANNOTATIONS(JDK8, Fragments.FeatureTypeAnnotations, DiagKind.PLURAL),
+        ANNOTATIONS_AFTER_TYPE_PARAMS(JDK8, Fragments.FeatureAnnotationsAfterTypeParams, DiagKind.PLURAL),
+        REPEATED_ANNOTATIONS(JDK8, Fragments.FeatureRepeatableAnnotations, DiagKind.PLURAL),
+        INTERSECTION_TYPES_IN_CAST(JDK8, Fragments.FeatureIntersectionTypesInCast, DiagKind.PLURAL),
+        GRAPH_INFERENCE(JDK8),
+        FUNCTIONAL_INTERFACE_MOST_SPECIFIC(JDK8),
+        POST_APPLICABILITY_VARARGS_ACCESS_CHECK(JDK8),
+        MAP_CAPTURES_TO_BOUNDS(MIN, JDK7),
+        PRIVATE_SAFE_VARARGS(JDK9),
+        DIAMOND_WITH_ANONYMOUS_CLASS_CREATION(JDK9, Fragments.FeatureDiamondAndAnonClass, DiagKind.NORMAL),
+        UNDERSCORE_IDENTIFIER(MIN, JDK8),
+        PRIVATE_INTERFACE_METHODS(JDK9, Fragments.FeaturePrivateIntfMethods, DiagKind.PLURAL),
+        LOCAL_VARIABLE_TYPE_INFERENCE(JDK10);
+
+        enum DiagKind {
+            NORMAL,
+            PLURAL;
+        }
+
+        private final Source minLevel;
+        private final Source maxLevel;
+        private final Fragment optFragment;
+        private final DiagKind optKind;
+
+        Feature(Source minLevel) {
+            this(minLevel, null, null);
+        }
+
+        Feature(Source minLevel, Fragment optFragment, DiagKind optKind) {
+            this(minLevel, MAX, optFragment, optKind);
+        }
+
+        Feature(Source minLevel, Source maxLevel) {
+            this(minLevel, maxLevel, null, null);
+        }
+
+        Feature(Source minLevel, Source maxLevel, Fragment optFragment, DiagKind optKind) {
+            this.minLevel = minLevel;
+            this.maxLevel = maxLevel;
+            this.optFragment = optFragment;
+            this.optKind = optKind;
+        }
+
+        public boolean allowedInSource(Source source) {
+            return source.compareTo(minLevel) >= 0 &&
+                    source.compareTo(maxLevel) <= 0;
+        }
+
+        public Fragment fragment(String sourceName) {
+            Assert.checkNonNull(optFragment);
+            return optKind == DiagKind.NORMAL ?
+                    Fragments.FeatureNotSupportedInSource(optFragment, sourceName, minLevel.name) :
+                    Fragments.FeatureNotSupportedInSourcePlural(optFragment, sourceName, minLevel.name);
+        }
+
+        public Error error(String sourceName) {
+            Assert.checkNonNull(optFragment);
+            return optKind == DiagKind.NORMAL ?
+                    Errors.FeatureNotSupportedInSource(optFragment, sourceName, minLevel.name) :
+                    Errors.FeatureNotSupportedInSourcePlural(optFragment, sourceName, minLevel.name);
+        }
     }
-    public boolean allowMethodReferences() {
-        return compareTo(JDK1_8) >= 0;
-    }
-    public boolean allowDefaultMethods() {
-        return compareTo(JDK1_8) >= 0;
-    }
-    public boolean allowStaticInterfaceMethods() {
-        return compareTo(JDK1_8) >= 0;
-    }
-    public boolean allowStrictMethodClashCheck() {
-        return compareTo(JDK1_8) >= 0;
-    }
-    public boolean allowEffectivelyFinalInInnerClasses() {
-        return compareTo(JDK1_8) >= 0;
-    }
-    public boolean allowTypeAnnotations() {
-        return compareTo(JDK1_8) >= 0;
-    }
-    public boolean allowAnnotationsAfterTypeParams() {
-        return compareTo(JDK1_8) >= 0;
-    }
-    public boolean allowRepeatedAnnotations() {
-        return compareTo(JDK1_8) >= 0;
-    }
-    public boolean allowIntersectionTypesInCast() {
-        return compareTo(JDK1_8) >= 0;
-    }
-    public boolean allowGraphInference() {
-        return compareTo(JDK1_8) >= 0;
-    }
-    public boolean allowFunctionalInterfaceMostSpecific() {
-        return compareTo(JDK1_8) >= 0;
-    }
-    public boolean allowPostApplicabilityVarargsAccessCheck() {
-        return compareTo(JDK1_8) >= 0;
-    }
-    public boolean mapCapturesToBounds() {
-        return compareTo(JDK1_8) < 0;
-    }
-    public boolean allowPrivateSafeVarargs() {
-        return compareTo(JDK1_9) >= 0;
-    }
-    public boolean allowDiamondWithAnonymousClassCreation() {
-        return compareTo(JDK1_9) >= 0;
-    }
-    public boolean allowUnderscoreIdentifier() {
-        return compareTo(JDK1_8) <= 0;
-    }
-    public boolean allowPrivateInterfaceMethods() { return compareTo(JDK1_9) >= 0; }
-    public boolean allowLocalVariableTypeInference() { return compareTo(JDK1_10) >= 0; }
+
     public static SourceVersion toSourceVersion(Source source) {
         switch(source) {
         case JDK1_2:
@@ -236,17 +235,17 @@
             return RELEASE_3;
         case JDK1_4:
             return RELEASE_4;
-        case JDK1_5:
+        case JDK5:
             return RELEASE_5;
-        case JDK1_6:
+        case JDK6:
             return RELEASE_6;
-        case JDK1_7:
+        case JDK7:
             return RELEASE_7;
-        case JDK1_8:
+        case JDK8:
             return RELEASE_8;
-        case JDK1_9:
+        case JDK9:
             return RELEASE_9;
-        case JDK1_10:
+        case JDK10:
             return RELEASE_10;
         default:
             return null;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Mon Dec 04 17:54:49 2017 +0000
@@ -35,6 +35,7 @@
 import javax.lang.model.element.ElementVisitor;
 
 import com.sun.tools.javac.code.Scope.WriteableScope;
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.Completer;
 import com.sun.tools.javac.code.Symbol.CompletionFailure;
@@ -468,7 +469,7 @@
         scope.enter(errSymbol);
 
         Source source = Source.instance(context);
-        if (source.allowModules()) {
+        if (Feature.MODULES.allowedInSource(source)) {
             java_base = enterModule(names.java_base);
             //avoid completing java.base during the Symtab initialization
             java_base.completer = Completer.NULL_COMPLETER;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Mon Dec 04 17:54:49 2017 +0000
@@ -41,6 +41,7 @@
 
 import com.sun.tools.javac.code.Attribute.RetentionPolicy;
 import com.sun.tools.javac.code.Lint.LintCategory;
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
 import com.sun.tools.javac.code.TypeMetadata.Entry.Kind;
 import com.sun.tools.javac.comp.AttrContext;
@@ -113,9 +114,9 @@
         syms = Symtab.instance(context);
         names = Names.instance(context);
         Source source = Source.instance(context);
-        allowObjectToPrimitiveCast = source.allowObjectToPrimitiveCast();
-        allowDefaultMethods = source.allowDefaultMethods();
-        mapCapturesToBounds = source.mapCapturesToBounds();
+        allowObjectToPrimitiveCast = Feature.OBJECT_TO_PRIMITIVE_CAST.allowedInSource(source);
+        allowDefaultMethods = Feature.DEFAULT_METHODS.allowedInSource(source);
+        mapCapturesToBounds = Feature.MAP_CAPTURES_TO_BOUNDS.allowedInSource(source);
         chk = Check.instance(context);
         enter = Enter.instance(context);
         capturedName = names.fromString("<captured wildcard>");
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Analyzer.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Analyzer.java	Mon Dec 04 17:54:49 2017 +0000
@@ -29,6 +29,7 @@
 
 import com.sun.source.tree.LambdaExpressionTree;
 import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.code.Type;
 import com.sun.tools.javac.code.Types;
 import com.sun.tools.javac.comp.ArgumentAttr.LocalCacheContext;
@@ -128,7 +129,7 @@
         String findOpt = options.get("find");
         //parse modes
         Source source = Source.instance(context);
-        allowDiamondWithAnonymousClassCreation = source.allowDiamondWithAnonymousClassCreation();
+        allowDiamondWithAnonymousClassCreation = Feature.DIAMOND_WITH_ANONYMOUS_CLASS_CREATION.allowedInSource(source);
         analyzerModes = AnalyzerMode.getAnalyzerModes(findOpt, source);
     }
 
@@ -137,17 +138,17 @@
      * the {@code -XDfind} option.
      */
     enum AnalyzerMode {
-        DIAMOND("diamond", Source::allowDiamond),
-        LAMBDA("lambda", Source::allowLambda),
-        METHOD("method", Source::allowGraphInference),
-        LOCAL("local", Source::allowLocalVariableTypeInference);
+        DIAMOND("diamond", Feature.DIAMOND),
+        LAMBDA("lambda", Feature.LAMBDA),
+        METHOD("method", Feature.GRAPH_INFERENCE),
+        LOCAL("local", Feature.LOCAL_VARIABLE_TYPE_INFERENCE);
 
         final String opt;
-        final Predicate<Source> sourceFilter;
+        final Feature feature;
 
-        AnalyzerMode(String opt, Predicate<Source> sourceFilter) {
+        AnalyzerMode(String opt, Feature feature) {
             this.opt = opt;
-            this.sourceFilter = sourceFilter;
+            this.feature = feature;
         }
 
         /**
@@ -168,7 +169,7 @@
             for (AnalyzerMode mode : values()) {
                 if (modes.contains(mode.opt)) {
                     res.add(mode);
-                } else if (modes.contains("-" + mode.opt) || !mode.sourceFilter.test(source)) {
+                } else if (modes.contains("-" + mode.opt) || !mode.feature.allowedInSource(source)) {
                     res.remove(mode);
                 }
             }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java	Mon Dec 04 17:54:49 2017 +0000
@@ -30,10 +30,12 @@
 import com.sun.tools.javac.code.Attribute.TypeCompound;
 import com.sun.tools.javac.code.Kinds.KindSelector;
 import com.sun.tools.javac.code.Scope.WriteableScope;
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.TypeMetadata.Entry.Kind;
 import com.sun.tools.javac.comp.Check.CheckContext;
 import com.sun.tools.javac.resources.CompilerProperties.Errors;
+import com.sun.tools.javac.resources.CompilerProperties.Fragments;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.tree.TreeInfo;
@@ -121,7 +123,7 @@
         theUnfinishedDefaultValue =  new Attribute.Error(syms.errType);
 
         Source source = Source.instance(context);
-        allowRepeatedAnnos = source.allowRepeatedAnnotations();
+        allowRepeatedAnnos = Feature.REPEATED_ANNOTATIONS.allowedInSource(source);
         sourceName = source.name;
 
         blockCount = 1;
@@ -344,7 +346,7 @@
 
             if (annotated.containsKey(a.type.tsym)) {
                 if (!allowRepeatedAnnos) {
-                    log.error(DiagnosticFlag.SOURCE_LEVEL, a.pos(), Errors.RepeatableAnnotationsNotSupportedInSource(sourceName));
+                    log.error(DiagnosticFlag.SOURCE_LEVEL, a.pos(), Feature.REPEATED_ANNOTATIONS.error(sourceName));
                 }
                 ListBuffer<T> l = annotated.get(a.type.tsym);
                 l = l.append(c);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Dec 04 17:54:49 2017 +0000
@@ -38,6 +38,7 @@
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Lint.LintCategory;
 import com.sun.tools.javac.code.Scope.WriteableScope;
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.code.TypeMetadata.Annotations;
@@ -150,12 +151,12 @@
         Options options = Options.instance(context);
 
         Source source = Source.instance(context);
-        allowStringsInSwitch = source.allowStringsInSwitch();
-        allowPoly = source.allowPoly();
-        allowTypeAnnos = source.allowTypeAnnotations();
-        allowLambda = source.allowLambda();
-        allowDefaultMethods = source.allowDefaultMethods();
-        allowStaticInterfaceMethods = source.allowStaticInterfaceMethods();
+        allowStringsInSwitch = Feature.STRINGS_IN_SWITCH.allowedInSource(source);
+        allowPoly = Feature.POLY.allowedInSource(source);
+        allowTypeAnnos = Feature.TYPE_ANNOTATIONS.allowedInSource(source);
+        allowLambda = Feature.LAMBDA.allowedInSource(source);
+        allowDefaultMethods = Feature.DEFAULT_METHODS.allowedInSource(source);
+        allowStaticInterfaceMethods = Feature.STATIC_INTERFACE_METHODS.allowedInSource(source);
         sourceName = source.name;
         useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning");
 
@@ -1392,7 +1393,7 @@
             boolean enumSwitch = (seltype.tsym.flags() & Flags.ENUM) != 0;
             boolean stringSwitch = types.isSameType(seltype, syms.stringType);
             if (stringSwitch && !allowStringsInSwitch) {
-                log.error(DiagnosticFlag.SOURCE_LEVEL, tree.selector.pos(), Errors.StringSwitchNotSupportedInSource(sourceName));
+                log.error(DiagnosticFlag.SOURCE_LEVEL, tree.selector.pos(), Feature.STRINGS_IN_SWITCH.error(sourceName));
             }
             if (!enumSwitch && !stringSwitch)
                 seltype = chk.checkType(tree.selector.pos(), seltype, syms.intType);
@@ -3667,7 +3668,7 @@
             }
             if (!allowStaticInterfaceMethods && sitesym.isInterface() &&
                     sym.isStatic() && sym.kind == MTH) {
-                log.error(DiagnosticFlag.SOURCE_LEVEL, tree.pos(), Errors.StaticIntfMethodInvokeNotSupportedInSource(sourceName));
+                log.error(DiagnosticFlag.SOURCE_LEVEL, tree.pos(), Feature.STATIC_INTERFACE_METHODS_INVOKE.error(sourceName));
             }
         } else if (sym.kind != ERR &&
                    (sym.flags() & STATIC) != 0 &&
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Mon Dec 04 17:54:49 2017 +0000
@@ -33,6 +33,7 @@
 import com.sun.tools.javac.code.Attribute.Compound;
 import com.sun.tools.javac.code.Directive.ExportsDirective;
 import com.sun.tools.javac.code.Directive.RequiresDirective;
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
 import com.sun.tools.javac.jvm.*;
 import com.sun.tools.javac.resources.CompilerProperties.Errors;
@@ -127,11 +128,6 @@
         fileManager = context.get(JavaFileManager.class);
 
         source = Source.instance(context);
-        allowSimplifiedVarargs = source.allowSimplifiedVarargs();
-        allowDefaultMethods = source.allowDefaultMethods();
-        allowStrictMethodClashCheck = source.allowStrictMethodClashCheck();
-        allowPrivateSafeVarargs = source.allowPrivateSafeVarargs();
-        allowDiamondWithAnonymousClassCreation = source.allowDiamondWithAnonymousClassCreation();
         warnOnAnyAccessToMembers = options.isSet("warnOnAccessToMembers");
 
         Target target = Target.instance(context);
@@ -156,26 +152,6 @@
         deferredLintHandler = DeferredLintHandler.instance(context);
     }
 
-    /** Switch: simplified varargs enabled?
-     */
-    boolean allowSimplifiedVarargs;
-
-    /** Switch: default methods enabled?
-     */
-    boolean allowDefaultMethods;
-
-    /** Switch: should unrelated return types trigger a method clash?
-     */
-    boolean allowStrictMethodClashCheck;
-
-    /** Switch: can the @SafeVarargs annotation be applied to private methods?
-     */
-    boolean allowPrivateSafeVarargs;
-
-    /** Switch: can diamond inference be used in anonymous instance creation ?
-     */
-    boolean allowDiamondWithAnonymousClassCreation;
-
     /** Character for synthetic names
      */
     char syntheticNameChar;
@@ -256,7 +232,7 @@
      *  @param pos        Position to be used for error reporting.
      */
     void warnUnsafeVararg(DiagnosticPosition pos, String key, Object... args) {
-        if (lint.isEnabled(LintCategory.VARARGS) && allowSimplifiedVarargs)
+        if (lint.isEnabled(LintCategory.VARARGS) && Feature.SIMPLIFIED_VARARGS.allowedInSource(source))
             log.warning(LintCategory.VARARGS, pos, key, args);
     }
 
@@ -814,9 +790,9 @@
                 t.isErroneous()) {
             return checkClassType(tree.clazz.pos(), t, true);
         } else {
-            if (tree.def != null && !allowDiamondWithAnonymousClassCreation) {
+            if (tree.def != null && !Feature.DIAMOND_WITH_ANONYMOUS_CLASS_CREATION.allowedInSource(source)) {
                 log.error(DiagnosticFlag.SOURCE_LEVEL, tree.clazz.pos(),
-                        Errors.CantApplyDiamond1(t, Fragments.DiamondAndAnonClassNotSupportedInSource(source.name)));
+                        Errors.CantApplyDiamond1(t, Feature.DIAMOND_WITH_ANONYMOUS_CLASS_CREATION.fragment(source.name)));
             }
             if (t.tsym.type.getTypeArguments().isEmpty()) {
                 log.error(tree.clazz.pos(),
@@ -906,7 +882,7 @@
 
     void checkVarargsMethodDecl(Env<AttrContext> env, JCMethodDecl tree) {
         MethodSymbol m = tree.sym;
-        if (!allowSimplifiedVarargs) return;
+        if (!Feature.SIMPLIFIED_VARARGS.allowedInSource(source)) return;
         boolean hasTrustMeAnno = m.attribute(syms.trustMeType.tsym) != null;
         Type varargElemType = null;
         if (m.isVarArgs()) {
@@ -914,7 +890,7 @@
         }
         if (hasTrustMeAnno && !isTrustMeAllowedOnMethod(m)) {
             if (varargElemType != null) {
-                JCDiagnostic msg = allowPrivateSafeVarargs ?
+                JCDiagnostic msg = Feature.PRIVATE_SAFE_VARARGS.allowedInSource(source) ?
                         diags.fragment(Fragments.VarargsTrustmeOnVirtualVarargs(m)) :
                         diags.fragment(Fragments.VarargsTrustmeOnVirtualVarargsFinalOnly(m));
                 log.error(tree,
@@ -942,7 +918,7 @@
             return (s.flags() & VARARGS) != 0 &&
                 (s.isConstructor() ||
                     (s.flags() & (STATIC | FINAL |
-                                  (allowPrivateSafeVarargs ? PRIVATE : 0) )) != 0);
+                                  (Feature.PRIVATE_SAFE_VARARGS.allowedInSource(source) ? PRIVATE : 0) )) != 0);
         }
 
     Type checkLocalVarType(DiagnosticPosition pos, Type t, Name name) {
@@ -1019,7 +995,7 @@
         if (useVarargs) {
             Type argtype = owntype.getParameterTypes().last();
             if (!types.isReifiable(argtype) &&
-                (!allowSimplifiedVarargs ||
+                (!Feature.SIMPLIFIED_VARARGS.allowedInSource(source) ||
                  sym.baseSymbol().attribute(syms.trustMeType.tsym) == null ||
                  !isTrustMeAllowedOnMethod(sym))) {
                 warnUnchecked(env.tree.pos(),
@@ -2489,7 +2465,7 @@
                 if (m2 == m1) continue;
                 //if (i) the signature of 'sym' is not a subsignature of m1 (seen as
                 //a member of 'site') and (ii) m1 has the same erasure as m2, issue an error
-                if (!types.isSubSignature(sym.type, types.memberType(site, m2), allowStrictMethodClashCheck) &&
+                if (!types.isSubSignature(sym.type, types.memberType(site, m2), Feature.STRICT_METHOD_CLASH_CHECK.allowedInSource(source)) &&
                         types.hasSameArgs(m2.erasure(types), m1.erasure(types))) {
                     sym.flags_field |= CLASH;
                     if (m1 == sym) {
@@ -2534,7 +2510,7 @@
         for (Symbol s : types.membersClosure(site, true).getSymbolsByName(sym.name, cf)) {
             //if (i) the signature of 'sym' is not a subsignature of m1 (seen as
             //a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error
-            if (!types.isSubSignature(sym.type, types.memberType(site, s), allowStrictMethodClashCheck)) {
+            if (!types.isSubSignature(sym.type, types.memberType(site, s), Feature.STRICT_METHOD_CLASH_CHECK.allowedInSource(source))) {
                 if (types.hasSameArgs(s.erasure(types), sym.erasure(types))) {
                     log.error(pos,
                               Errors.NameClashSameErasureNoHide(sym, sym.location(), s, s.location()));
@@ -2634,7 +2610,7 @@
     void checkPotentiallyAmbiguousOverloads(DiagnosticPosition pos, Type site,
             MethodSymbol msym1, MethodSymbol msym2) {
         if (msym1 != msym2 &&
-                allowDefaultMethods &&
+                Feature.DEFAULT_METHODS.allowedInSource(source) &&
                 lint.isEnabled(LintCategory.OVERLOADS) &&
                 (msym1.flags() & POTENTIALLY_AMBIGUOUS) == 0 &&
                 (msym2.flags() & POTENTIALLY_AMBIGUOUS) == 0) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java	Mon Dec 04 17:54:49 2017 +0000
@@ -32,6 +32,7 @@
 import com.sun.source.tree.LambdaExpressionTree.BodyKind;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Scope.WriteableScope;
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.resources.CompilerProperties.Errors;
 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
 import com.sun.tools.javac.tree.*;
@@ -291,10 +292,10 @@
         rs = Resolve.instance(context);
         diags = JCDiagnostic.Factory.instance(context);
         Source source = Source.instance(context);
-        allowImprovedRethrowAnalysis = source.allowImprovedRethrowAnalysis();
-        allowImprovedCatchAnalysis = source.allowImprovedCatchAnalysis();
-        allowEffectivelyFinalInInnerClasses = source.allowEffectivelyFinalInInnerClasses();
-        enforceThisDotInit = source.enforceThisDotInit();
+        allowImprovedRethrowAnalysis = Feature.IMPROVED_RETHROW_ANALYSIS.allowedInSource(source);
+        allowImprovedCatchAnalysis = Feature.IMPROVED_CATCH_ANALYSIS.allowedInSource(source);
+        allowEffectivelyFinalInInnerClasses = Feature.EFFECTIVELY_FINAL_IN_INNER_CLASSES.allowedInSource(source);
+        enforceThisDotInit = Feature.ENFORCE_THIS_DOT_INIT.allowedInSource(source);
     }
 
     /**
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Dec 04 17:54:49 2017 +0000
@@ -25,6 +25,7 @@
 
 package com.sun.tools.javac.comp;
 
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.code.Type.UndetVar.UndetVarListener;
 import com.sun.tools.javac.code.Types.TypeMapping;
 import com.sun.tools.javac.comp.Attr.CheckMode;
@@ -116,7 +117,8 @@
         log = Log.instance(context);
         inferenceException = new InferenceException(diags);
         Options options = Options.instance(context);
-        allowGraphInference = Source.instance(context).allowGraphInference()
+        Source source = Source.instance(context);
+        allowGraphInference = Feature.GRAPH_INFERENCE.allowedInSource(source)
                 && options.isUnset("useLegacyInference");
         dependenciesFolder = options.get("debug.dumpInferenceGraphsTo");
         pendingGraphs = List.nil();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java	Mon Dec 04 17:54:49 2017 +0000
@@ -66,6 +66,7 @@
 import com.sun.tools.javac.code.Lint.LintCategory;
 import com.sun.tools.javac.code.ModuleFinder;
 import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.Completer;
@@ -185,7 +186,7 @@
         types = Types.instance(context);
         fileManager = context.get(JavaFileManager.class);
         source = Source.instance(context);
-        allowModules = source.allowModules();
+        allowModules = Feature.MODULES.allowedInSource(source);
         Options options = Options.instance(context);
 
         allowAccessIntoSystem = options.isUnset(Option.RELEASE);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Dec 04 17:54:49 2017 +0000
@@ -28,6 +28,7 @@
 import com.sun.tools.javac.api.Formattable.LocalizedString;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Scope.WriteableScope;
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.comp.Attr.ResultInfo;
@@ -137,15 +138,15 @@
         verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
         Target target = Target.instance(context);
         allowMethodHandles = target.hasMethodHandles();
-        allowFunctionalInterfaceMostSpecific = source.allowFunctionalInterfaceMostSpecific();
-        allowLocalVariableTypeInference = source.allowLocalVariableTypeInference();
+        allowFunctionalInterfaceMostSpecific = Feature.FUNCTIONAL_INTERFACE_MOST_SPECIFIC.allowedInSource(source);
+        allowLocalVariableTypeInference = Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source);
         checkVarargsAccessAfterResolution =
-                source.allowPostApplicabilityVarargsAccessCheck();
+                Feature.POST_APPLICABILITY_VARARGS_ACCESS_CHECK.allowedInSource(source);
         polymorphicSignatureScope = WriteableScope.create(syms.noSymbol);
 
         inapplicableMethodException = new InapplicableMethodException(diags);
 
-        allowModules = source.allowModules();
+        allowModules = Feature.MODULES.allowedInSource(source);
     }
 
     /** error symbols, which are returned when resolution fails
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java	Mon Dec 04 17:54:49 2017 +0000
@@ -29,6 +29,7 @@
 
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Attribute.TypeCompound;
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.resources.CompilerProperties.Errors;
 import com.sun.tools.javac.tree.*;
@@ -94,8 +95,8 @@
         make = TreeMaker.instance(context);
         resolve = Resolve.instance(context);
         Source source = Source.instance(context);
-        allowInterfaceBridges = source.allowDefaultMethods();
-        allowGraphInference = source.allowGraphInference();
+        allowInterfaceBridges = Feature.DEFAULT_METHODS.allowedInSource(source);
+        allowGraphInference = Feature.GRAPH_INFERENCE.allowedInSource(source);
         annotate = Annotate.instance(context);
         attr = Attr.instance(context);
     }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Mon Dec 04 17:54:49 2017 +0000
@@ -37,6 +37,7 @@
 import com.sun.tools.javac.code.Scope.NamedImportScope;
 import com.sun.tools.javac.code.Scope.StarImportScope;
 import com.sun.tools.javac.code.Scope.WriteableScope;
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.util.*;
@@ -137,8 +138,8 @@
         typeEnvs = TypeEnvs.instance(context);
         dependencies = Dependencies.instance(context);
         Source source = Source.instance(context);
-        allowTypeAnnos = source.allowTypeAnnotations();
-        allowDeprecationOnImport = source.allowDeprecationOnImport();
+        allowTypeAnnos = Feature.TYPE_ANNOTATIONS.allowedInSource(source);
+        allowDeprecationOnImport = Feature.DEPRECATION_ON_IMPORT.allowedInSource(source);
     }
 
     /** Switch: support type annotations.
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Dec 04 17:54:49 2017 +0000
@@ -42,6 +42,7 @@
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
 
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.comp.Annotate;
 import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
 import com.sun.tools.javac.code.*;
@@ -246,8 +247,8 @@
         verbose         = options.isSet(Option.VERBOSE);
 
         Source source = Source.instance(context);
-        allowSimplifiedVarargs = source.allowSimplifiedVarargs();
-        allowModules     = source.allowModules();
+        allowSimplifiedVarargs = Feature.SIMPLIFIED_VARARGS.allowedInSource(source);
+        allowModules     = Feature.MODULES.allowedInSource(source);
 
         saveParameterNames = options.isSet(PARAMETERS);
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java	Mon Dec 04 17:54:49 2017 +0000
@@ -54,6 +54,7 @@
 import com.sun.tools.doclint.DocLint;
 import com.sun.tools.javac.code.Lint.LintCategory;
 import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.file.BaseFileManager;
 import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.jvm.Profile;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Mon Dec 04 17:54:49 2017 +0000
@@ -52,6 +52,7 @@
 import com.sun.tools.javac.api.MultiTaskListener;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Lint.LintCategory;
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.CompletionFailure;
 import com.sun.tools.javac.code.Symbol.PackageSymbol;
@@ -684,7 +685,7 @@
         if (sep == -1) {
             msym = modules.getDefaultModule();
             typeName = name;
-        } else if (source.allowModules()) {
+        } else if (Feature.MODULES.allowedInSource(source)) {
             Name modName = names.fromString(name.substring(0, sep));
 
             msym = moduleFinder.findModule(modName);
@@ -1544,7 +1545,7 @@
             env.tree = transTypes.translateTopLevelClass(env.tree, localMake);
             compileStates.put(env, CompileState.TRANSTYPES);
 
-            if (source.allowLambda() && scanner.hasLambdas) {
+            if (Feature.LAMBDA.allowedInSource(source) && scanner.hasLambdas) {
                 if (shouldStop(CompileState.UNLAMBDA))
                     return;
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java	Mon Dec 04 17:54:49 2017 +0000
@@ -51,6 +51,7 @@
 import com.sun.tools.javac.code.Directive.RequiresDirective;
 import com.sun.tools.javac.code.Directive.RequiresFlag;
 import com.sun.tools.javac.code.Scope.WriteableScope;
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.comp.AttrContext;
 import com.sun.tools.javac.comp.Enter;
@@ -114,7 +115,7 @@
         javacTaskImpl = t instanceof JavacTaskImpl ? (JavacTaskImpl) t : null;
         log = Log.instance(context);
         Source source = Source.instance(context);
-        allowModules = source.allowModules();
+        allowModules = Feature.MODULES.allowedInSource(source);
     }
 
     @Override @DefinedBy(Api.LANGUAGE_MODEL)
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java	Mon Dec 04 17:54:49 2017 +0000
@@ -26,8 +26,11 @@
 package com.sun.tools.javac.parser;
 
 import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
 import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
 
 import java.nio.CharBuffer;
 
@@ -46,14 +49,6 @@
 
     private static final boolean scannerDebug = false;
 
-    /** Allow binary literals.
-     */
-    private boolean allowBinaryLiterals;
-
-    /** Allow underscores in literals.
-     */
-    private boolean allowUnderscoresInLiterals;
-
     /** The source language setting.
      */
     private Source source;
@@ -121,14 +116,24 @@
         this.tokens = fac.tokens;
         this.source = fac.source;
         this.reader = reader;
-        this.allowBinaryLiterals = source.allowBinaryLiterals();
-        this.allowUnderscoresInLiterals = source.allowUnderscoresInLiterals();
+    }
+
+    private void checkSourceLevel(int pos, Feature feature) {
+        if (!feature.allowedInSource(source)) {
+            lexError(DiagnosticFlag.SOURCE_LEVEL, pos, feature.error(source.name));
+        }
     }
 
     /** Report an error at the given position using the provided arguments.
      */
-    protected void lexError(int pos, String key, Object... args) {
-        log.error(pos, key, args);
+    protected void lexError(int pos, JCDiagnostic.Error key) {
+        log.error(pos, key);
+        tk = TokenKind.ERROR;
+        errPos = pos;
+    }
+
+    protected void lexError(DiagnosticFlag flags, int pos, JCDiagnostic.Error key) {
+        log.error(flags, pos, key);
         tk = TokenKind.ERROR;
         errPos = pos;
     }
@@ -175,7 +180,7 @@
                 case '\\':
                     reader.putChar('\\', true); break;
                 default:
-                    lexError(reader.bp, "illegal.esc.char");
+                    lexError(reader.bp, Errors.IllegalEscChar);
                 }
             }
         } else if (reader.bp != reader.buflen) {
@@ -190,17 +195,14 @@
             if (reader.ch != '_') {
                 reader.putChar(false);
             } else {
-                if (!allowUnderscoresInLiterals) {
-                    lexError(pos, "unsupported.underscore.lit", source.name);
-                    allowUnderscoresInLiterals = true;
-                }
+                checkSourceLevel(pos, Feature.UNDERSCORES_IN_LITERALS);
             }
             saveCh = reader.ch;
             savePos = reader.bp;
             reader.scanChar();
         } while (reader.digit(pos, digitRadix) >= 0 || reader.ch == '_');
         if (saveCh == '_')
-            lexError(savePos, "illegal.underscore");
+            lexError(savePos, Errors.IllegalUnderscore);
     }
 
     /** Read fractional part of hexadecimal floating point number.
@@ -216,11 +218,11 @@
             if (reader.digit(pos, 10) >= 0) {
                 scanDigits(pos, 10);
                 if (!hexFloatsWork)
-                    lexError(pos, "unsupported.cross.fp.lit");
+                    lexError(pos, Errors.UnsupportedCrossFpLit);
             } else
-                lexError(pos, "malformed.fp.lit");
+                lexError(pos, Errors.MalformedFpLit);
         } else {
-            lexError(pos, "malformed.fp.lit");
+            lexError(pos, Errors.MalformedFpLit);
         }
         if (reader.ch == 'f' || reader.ch == 'F') {
             reader.putChar(true);
@@ -254,7 +256,7 @@
                 scanDigits(pos, 10);
                 return;
             }
-            lexError(pos, "malformed.fp.lit");
+            lexError(pos, Errors.MalformedFpLit);
             reader.sp = sp1;
         }
     }
@@ -287,14 +289,14 @@
             scanDigits(pos, 16);
         }
         if (!seendigit)
-            lexError(pos, "invalid.hex.number");
+            lexError(pos, Errors.InvalidHexNumber);
         else
             scanHexExponentAndSuffix(pos);
     }
 
     private void skipIllegalUnderscores() {
         if (reader.ch == '_') {
-            lexError(reader.bp, "illegal.underscore");
+            lexError(reader.bp, Errors.IllegalUnderscore);
             while (reader.ch == '_')
                 reader.scanChar();
         }
@@ -329,10 +331,10 @@
             if (!seenValidDigit) {
                 switch (radix) {
                 case 2:
-                    lexError(pos, "invalid.binary.number");
+                    lexError(pos, Errors.InvalidBinaryNumber);
                     break;
                 case 16:
-                    lexError(pos, "invalid.hex.number");
+                    lexError(pos, Errors.InvalidHexNumber);
                     break;
                 }
             }
@@ -504,10 +506,7 @@
                         skipIllegalUnderscores();
                         scanNumber(pos, 16);
                     } else if (reader.ch == 'b' || reader.ch == 'B') {
-                        if (!allowBinaryLiterals) {
-                            lexError(pos, "unsupported.binary.lit", source.name);
-                            allowBinaryLiterals = true;
-                        }
+                        checkSourceLevel(pos, Feature.BINARY_LITERALS);
                         reader.scanChar();
                         skipIllegalUnderscores();
                         scanNumber(pos, 2);
@@ -519,7 +518,7 @@
                                 reader.scanChar();
                             } while (reader.ch == '_');
                             if (reader.digit(pos, 10) < 0) {
-                                lexError(savePos, "illegal.underscore");
+                                lexError(savePos, Errors.IllegalUnderscore);
                             }
                         }
                         scanNumber(pos, 8);
@@ -542,7 +541,7 @@
                             reader.putChar('.');
                             tk = TokenKind.ELLIPSIS;
                         } else {
-                            lexError(savePos, "illegal.dot");
+                            lexError(savePos, Errors.IllegalDot);
                         }
                     } else {
                         tk = TokenKind.DOT;
@@ -600,7 +599,7 @@
                             comments = addComment(comments, processComment(pos, reader.bp, style));
                             break;
                         } else {
-                            lexError(pos, "unclosed.comment");
+                            lexError(pos, Errors.UnclosedComment);
                             break loop;
                         }
                     } else if (reader.ch == '=') {
@@ -613,17 +612,17 @@
                 case '\'':
                     reader.scanChar();
                     if (reader.ch == '\'') {
-                        lexError(pos, "empty.char.lit");
+                        lexError(pos, Errors.EmptyCharLit);
                         reader.scanChar();
                     } else {
                         if (reader.ch == CR || reader.ch == LF)
-                            lexError(pos, "illegal.line.end.in.char.lit");
+                            lexError(pos, Errors.IllegalLineEndInCharLit);
                         scanLitChar(pos);
                         if (reader.ch == '\'') {
                             reader.scanChar();
                             tk = TokenKind.CHARLITERAL;
                         } else {
-                            lexError(pos, "unclosed.char.lit");
+                            lexError(pos, Errors.UnclosedCharLit);
                         }
                     }
                     break loop;
@@ -635,7 +634,7 @@
                         tk = TokenKind.STRINGLITERAL;
                         reader.scanChar();
                     } else {
-                        lexError(pos, "unclosed.str.lit");
+                        lexError(pos, Errors.UnclosedStrLit);
                     }
                     break loop;
                 default:
@@ -676,7 +675,7 @@
                                                 String.format("%s", reader.ch) :
                                                 String.format("\\u%04x", (int)reader.ch);
                             }
-                            lexError(pos, "illegal.char", arg);
+                            lexError(pos, Errors.IllegalChar(arg));
                             reader.scanChar();
                         }
                     }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Dec 04 17:54:49 2017 +0000
@@ -26,12 +26,15 @@
 package com.sun.tools.javac.parser;
 
 import java.util.*;
+import java.util.function.Function;
+import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
 import com.sun.source.tree.ModuleTree.ModuleKind;
 
 import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.parser.Tokens.*;
 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
 import com.sun.tools.javac.resources.CompilerProperties;
@@ -41,6 +44,7 @@
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import com.sun.tools.javac.util.JCDiagnostic.Error;
 import com.sun.tools.javac.util.List;
 
 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
@@ -163,23 +167,7 @@
         this.log = fac.log;
         this.names = fac.names;
         this.source = fac.source;
-        this.allowTWR = source.allowTryWithResources();
-        this.allowEffectivelyFinalVariablesInTWR =
-                source.allowEffectivelyFinalVariablesInTryWithResources();
-        this.allowDiamond = source.allowDiamond();
-        this.allowMulticatch = source.allowMulticatch();
         this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
-        this.allowLambda = source.allowLambda();
-        this.allowMethodReferences = source.allowMethodReferences();
-        this.allowDefaultMethods = source.allowDefaultMethods();
-        this.allowStaticInterfaceMethods = source.allowStaticInterfaceMethods();
-        this.allowIntersectionTypesInCast = source.allowIntersectionTypesInCast();
-        this.allowTypeAnnotations = source.allowTypeAnnotations();
-        this.allowModules = source.allowModules();
-        this.allowAnnotationsAfterTypeParams = source.allowAnnotationsAfterTypeParams();
-        this.allowUnderscoreIdentifier = source.allowUnderscoreIdentifier();
-        this.allowPrivateInterfaceMethods = source.allowPrivateInterfaceMethods();
-        this.allowLocalVariableTypeInference = source.allowLocalVariableTypeInference();
         this.keepDocComments = keepDocComments;
         this.parseModuleInfo = parseModuleInfo;
         docComments = newDocCommentTable(keepDocComments, fac);
@@ -198,54 +186,10 @@
         return keepDocComments ? new LazyDocCommentTable(fac) : null;
     }
 
-    /** Switch: Should diamond operator be recognized?
-     */
-    boolean allowDiamond;
-
-    /** Switch: Should multicatch clause be accepted?
-     */
-    boolean allowMulticatch;
-
-    /** Switch: should we recognize try-with-resources?
-     */
-    boolean allowTWR;
-
-    /** Switch: should we allow (effectively) final variables as resources in try-with-resources?
-     */
-    boolean allowEffectivelyFinalVariablesInTWR;
-
     /** Switch: should we fold strings?
      */
     boolean allowStringFolding;
 
-    /** Switch: should we recognize lambda expressions?
-     */
-    boolean allowLambda;
-
-    /** Switch: should we allow method/constructor references?
-     */
-    boolean allowMethodReferences;
-
-    /** Switch: should we recognize modules?
-     */
-    boolean allowModules;
-
-    /** Switch: should we allow default methods in interfaces?
-     */
-    boolean allowDefaultMethods;
-
-    /** Switch: should we allow static methods in interfaces?
-     */
-    boolean allowStaticInterfaceMethods;
-
-    /** Switch: should we allow private (instance) methods in interfaces?
-     */
-    boolean allowPrivateInterfaceMethods;
-
-    /** Switch: should we allow intersection types in cast?
-     */
-    boolean allowIntersectionTypesInCast;
-
     /** Switch: should we keep docComments?
      */
     boolean keepDocComments;
@@ -254,27 +198,11 @@
      */
     boolean keepLineMap;
 
-    /** Switch: should we recognize type annotations?
-     */
-    boolean allowTypeAnnotations;
-
-    /** Switch: should we allow annotations after the method type parameters?
-     */
-    boolean allowAnnotationsAfterTypeParams;
-
-    /** Switch: should we allow '_' as an identifier?
-     */
-    boolean allowUnderscoreIdentifier;
-
     /** Switch: is "this" allowed as an identifier?
      * This is needed to parse receiver types.
      */
     boolean allowThisIdent;
 
-    /** Switch: is local variable inference allowed?
-     */
-    boolean allowLocalVariableTypeInference;
-
     /** The type of the method receiver, as specified by a first "this" parameter.
      */
     JCVariableDecl receiverParam;
@@ -628,7 +556,7 @@
         } else if (token.kind == THIS) {
             if (allowThisIdent) {
                 // Make sure we're using a supported source version.
-                checkTypeAnnotations();
+                checkSourceLevel(Feature.TYPE_ANNOTATIONS);
                 Name name = token.name();
                 nextToken();
                 return name;
@@ -638,7 +566,7 @@
                 return names.error;
             }
         } else if (token.kind == UNDERSCORE) {
-            if (allowUnderscoreIdentifier) {
+            if (Feature.UNDERSCORE_IDENTIFIER.allowedInSource(source)) {
                 warning(token.pos, "underscore.as.identifier");
             } else {
                 error(token.pos, "underscore.as.identifier");
@@ -1170,7 +1098,7 @@
                        int pos1 = pos;
                        List<JCExpression> targets = List.of(t = parseType());
                        while (token.kind == AMP) {
-                           checkIntersectionTypesInCast();
+                           checkSourceLevel(Feature.INTERSECTION_TYPES_IN_CAST);
                            accept(AMP);
                            targets = targets.prepend(parseType());
                        }
@@ -1771,7 +1699,7 @@
     }
 
     JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) {
-        checkLambda();
+        checkSourceLevel(Feature.LAMBDA);
         accept(ARROW);
 
         return token.kind == LBRACE ?
@@ -1890,7 +1818,7 @@
         if (token.kind == LT) {
             nextToken();
             if (token.kind == GT && diamondAllowed) {
-                checkDiamond();
+                checkSourceLevel(Feature.DIAMOND);
                 mode |= DIAMOND;
                 nextToken();
                 return List.nil();
@@ -2065,7 +1993,7 @@
     }
 
     JCExpression memberReferenceSuffix(int pos1, JCExpression t) {
-        checkMethodReferences();
+        checkSourceLevel(Feature.METHOD_REFERENCES);
         mode = EXPR;
         List<JCExpression> typeArgs = null;
         if (token.kind == LT) {
@@ -2568,7 +2496,7 @@
             nextToken();
             List<JCTree> resources = List.nil();
             if (token.kind == LPAREN) {
-                checkTryWithResources();
+                checkSourceLevel(Feature.TRY_WITH_RESOURCES);
                 nextToken();
                 resources = resources();
                 accept(RPAREN);
@@ -2584,7 +2512,7 @@
                 }
             } else {
                 if (resources.isEmpty()) {
-                    if (allowTWR) {
+                    if (Feature.TRY_WITH_RESOURCES.allowedInSource(source)) {
                         error(pos, "try.without.catch.finally.or.resource.decls");
                     } else {
                         error(pos, "try.without.catch.or.finally");
@@ -2701,7 +2629,7 @@
         ListBuffer<JCExpression> catchTypes = new ListBuffer<>();
         catchTypes.add(parseType());
         while (token.kind == BAR) {
-            checkMulticatch();
+            checkSourceLevel(Feature.MULTICATCH);
             nextToken();
             // Instead of qualident this is now parseType.
             // But would that allow too much, e.g. arrays or generics?
@@ -2870,7 +2798,7 @@
             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
             case STRICTFP    : flag = Flags.STRICTFP; break;
             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
-            case DEFAULT     : checkDefaultMethods(); flag = Flags.DEFAULT; break;
+            case DEFAULT     : checkSourceLevel(Feature.DEFAULT_METHODS); flag = Flags.DEFAULT; break;
             case ERROR       : flag = 0; nextToken(); break;
             default: break loop;
             }
@@ -2914,7 +2842,7 @@
     JCAnnotation annotation(int pos, Tag kind) {
         // accept(AT); // AT consumed by caller
         if (kind == Tag.TYPE_ANNOTATION) {
-            checkTypeAnnotations();
+            checkSourceLevel(Feature.TYPE_ANNOTATIONS);
         }
         JCTree ident = qualident(false);
         List<JCExpression> fieldValues = annotationFieldValuesOpt();
@@ -3028,7 +2956,7 @@
                                                                      boolean localDecl)
     {
         JCVariableDecl head = variableDeclaratorRest(pos, mods, type, name, reqInit, dc, localDecl);
-        boolean implicit = allowLocalVariableTypeInference && head.vartype == null;
+        boolean implicit = Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source) && head.vartype == null;
         vdefs.append(head);
         while (token.kind == COMMA) {
             if (implicit) {
@@ -3066,7 +2994,7 @@
         else if (reqInit) syntaxError(token.pos, "expected", EQ);
         JCTree elemType = TreeInfo.innermostType(type, true);
         int startPos = Position.NOPOS;
-        if (allowLocalVariableTypeInference && elemType.hasTag(IDENT)) {
+        if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source) && elemType.hasTag(IDENT)) {
             Name typeName = ((JCIdent)elemType).name;
             if (isRestrictedLocalVarTypeName(typeName)) {
                 if (type.hasTag(TYPEARRAY)) {
@@ -3100,7 +3028,7 @@
     }
 
     boolean isRestrictedLocalVarTypeName(Name name) {
-        return allowLocalVariableTypeInference && name == names.var;
+        return Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source) && name == names.var;
     }
 
     /** VariableDeclaratorId = Ident BracketsOpt
@@ -3176,7 +3104,7 @@
             JCModifiers mods = toP(F.at(startPos).Modifiers(Flags.FINAL));
             return variableDeclaratorRest(token.pos, mods, t, ident(), true, null, true);
         } else {
-            checkVariableInTryWithResources(startPos);
+            checkSourceLevel(Feature.EFFECTIVELY_FINAL_VARIABLES_IN_TRY_WITH_RESOURCES);
             if (!t.hasTag(IDENT) && !t.hasTag(SELECT)) {
                 log.error(t.pos(), Errors.TryWithResourcesExprNeedsVar);
             }
@@ -3278,10 +3206,7 @@
 
     JCModuleDecl moduleDecl(JCModifiers mods, ModuleKind kind, Comment dc) {
         int pos = token.pos;
-        if (!allowModules) {
-            log.error(pos, Errors.ModulesNotSupportedInSource(source.name));
-            allowModules = true;
-        }
+        checkSourceLevel(Feature.MODULES);
 
         nextToken();
         JCExpression name = qualident(false);
@@ -3700,7 +3625,7 @@
                 List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION);
 
                 if (annosAfterParams.nonEmpty()) {
-                    checkAnnotationsAfterTypeParams(annosAfterParams.head.pos);
+                    checkSourceLevel(annosAfterParams.head.pos, Feature.ANNOTATIONS_AFTER_TYPE_PARAMS);
                     mods.annotations = mods.annotations.appendList(annosAfterParams);
                     if (mods.pos == Position.NOPOS)
                         mods.pos = mods.annotations.head.pos;
@@ -3768,10 +3693,10 @@
                               Comment dc) {
         if (isInterface) {
             if ((mods.flags & Flags.STATIC) != 0) {
-                checkStaticInterfaceMethods();
+                checkSourceLevel(Feature.STATIC_INTERFACE_METHODS);
             }
             if ((mods.flags & Flags.PRIVATE) != 0) {
-                checkPrivateInterfaceMethods();
+                checkSourceLevel(Feature.PRIVATE_INTERFACE_METHODS);
             }
         }
         JCVariableDecl prevReceiverParam = this.receiverParam;
@@ -4226,64 +4151,13 @@
         }
     }
 
-    void checkDiamond() {
-        if (!allowDiamond) {
-            log.error(DiagnosticFlag.SOURCE_LEVEL, token.pos, Errors.DiamondNotSupportedInSource(source.name));
-        }
-    }
-    void checkMulticatch() {
-        if (!allowMulticatch) {
-            log.error(DiagnosticFlag.SOURCE_LEVEL, token.pos, Errors.MulticatchNotSupportedInSource(source.name));
-        }
-    }
-    void checkTryWithResources() {
-        if (!allowTWR) {
-            log.error(DiagnosticFlag.SOURCE_LEVEL, token.pos, Errors.TryWithResourcesNotSupportedInSource(source.name));
-        }
-    }
-    void checkVariableInTryWithResources(int startPos) {
-        if (!allowEffectivelyFinalVariablesInTWR) {
-            log.error(DiagnosticFlag.SOURCE_LEVEL, startPos, Errors.VarInTryWithResourcesNotSupportedInSource(source.name));
-        }
-    }
-    void checkLambda() {
-        if (!allowLambda) {
-            log.error(DiagnosticFlag.SOURCE_LEVEL, token.pos, Errors.LambdaNotSupportedInSource(source.name));
-        }
+    void checkSourceLevel(Feature feature) {
+        checkSourceLevel(token.pos, feature);
     }
-    void checkMethodReferences() {
-        if (!allowMethodReferences) {
-            log.error(DiagnosticFlag.SOURCE_LEVEL, token.pos, Errors.MethodReferencesNotSupportedInSource(source.name));
-        }
-    }
-    void checkDefaultMethods() {
-        if (!allowDefaultMethods) {
-            log.error(DiagnosticFlag.SOURCE_LEVEL, token.pos, Errors.DefaultMethodsNotSupportedInSource(source.name));
-        }
-    }
-    void checkIntersectionTypesInCast() {
-        if (!allowIntersectionTypesInCast) {
-            log.error(DiagnosticFlag.SOURCE_LEVEL, token.pos, Errors.IntersectionTypesInCastNotSupportedInSource(source.name));
-        }
-    }
-    void checkStaticInterfaceMethods() {
-        if (!allowStaticInterfaceMethods) {
-            log.error(DiagnosticFlag.SOURCE_LEVEL, token.pos, Errors.StaticIntfMethodsNotSupportedInSource(source.name));
-        }
-    }
-    void checkTypeAnnotations() {
-        if (!allowTypeAnnotations) {
-            log.error(DiagnosticFlag.SOURCE_LEVEL, token.pos, Errors.TypeAnnotationsNotSupportedInSource(source.name));
-        }
-    }
-    void checkPrivateInterfaceMethods() {
-        if (!allowPrivateInterfaceMethods) {
-            log.error(DiagnosticFlag.SOURCE_LEVEL, token.pos, CompilerProperties.Errors.PrivateIntfMethodsNotSupportedInSource(source.name));
-        }
-    }
-    protected void checkAnnotationsAfterTypeParams(int pos) {
-        if (!allowAnnotationsAfterTypeParams) {
-            log.error(DiagnosticFlag.SOURCE_LEVEL, pos, Errors.AnnotationsAfterTypeParamsNotSupportedInSource(source.name));
+
+    protected void checkSourceLevel(int pos, Feature feature) {
+        if (!feature.allowedInSource(source)) {
+            log.error(DiagnosticFlag.SOURCE_LEVEL, pos, feature.error(source.name));
         }
     }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Mon Dec 04 17:54:49 2017 +0000
@@ -53,6 +53,7 @@
 import com.sun.tools.javac.api.MultiTaskListener;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Scope.WriteableScope;
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.ClassType;
 import com.sun.tools.javac.code.Types;
@@ -116,7 +117,6 @@
     private final boolean fatalErrors;
     private final boolean werror;
     private final boolean showResolveErrors;
-    private final boolean allowModules;
 
     private final JavacFiler filer;
     private final JavacMessager messager;
@@ -233,8 +233,6 @@
         initialCompleter = ClassFinder.instance(context).getCompleter();
         chk = Check.instance(context);
         initProcessorLoader();
-
-        allowModules = source.allowModules();
     }
 
     public void setProcessors(Iterable<? extends Processor> processors) {
@@ -770,7 +768,7 @@
 
                 if (psi.processorIterator.hasNext()) {
                     ProcessorState ps = new ProcessorState(psi.processorIterator.next(),
-                                                           log, source, allowModules,
+                                                           log, source, Feature.MODULES.allowedInSource(source),
                                                            JavacProcessingEnvironment.this);
                     psi.procStateList.add(ps);
                     return ps;
@@ -837,7 +835,7 @@
 
         for(TypeElement a  : annotationsPresent) {
             ModuleElement mod = elementUtils.getModuleOf(a);
-            String moduleSpec = allowModules && mod != null ? mod.getQualifiedName() + "/" : "";
+            String moduleSpec = Feature.MODULES.allowedInSource(source) && mod != null ? mod.getQualifiedName() + "/" : "";
             unmatchedAnnotations.put(moduleSpec + a.getQualifiedName().toString(),
                                      a);
         }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Dec 04 17:54:49 2017 +0000
@@ -2601,38 +2601,87 @@
     ({3})
 
 ########################################
-# Diagnostics for language feature changes
+# Diagnostics for language feature changes.
+# Such diagnostics have a common template which can be customized by using a feature
+# diagnostic fragment (one of those given below).
 ########################################
 
-# 0: string
-compiler.err.modules.not.supported.in.source=\
-   modules are not supported in -source {0}\n\
-    (use -source 9 or higher to enable modules)
-
-# 0: string
-compiler.misc.diamond.and.anon.class.not.supported.in.source=\
-    cannot use ''<>'' with anonymous inner classes in -source {0}\n\
-    (use -source 9 or higher to enable ''<>'' with anonymous inner classes)
-
-# 0: string
-compiler.err.unsupported.binary.lit=\
-    binary literals are not supported in -source {0}\n\
-    (use -source 7 or higher to enable binary literals)
-
-# 0: string
-compiler.err.unsupported.underscore.lit=\
-    underscores in literals are not supported in -source {0}\n\
-    (use -source 7 or higher to enable underscores in literals)
-
-# 0: string
-compiler.err.try.with.resources.not.supported.in.source=\
-    try-with-resources is not supported in -source {0}\n\
-    (use -source 7 or higher to enable try-with-resources)
-
-# 0: string
-compiler.err.var.in.try.with.resources.not.supported.in.source=\
-    variables in try-with-resources not supported in -source {0}\n\
-    (use -source 9 or higher to enable variables in try-with-resources)
+# 0: message segment (feature), 1: string (found version), 2: string (expected version)
+compiler.err.feature.not.supported.in.source=\
+   {0} is not supported in -source {1}\n\
+    (use -source {2} or higher to enable {0})
+
+# 0: message segment (feature), 1: string (found version), 2: string (expected version)
+compiler.err.feature.not.supported.in.source.plural=\
+   {0} are not supported in -source {1}\n\
+    (use -source {2} or higher to enable {0})
+
+# 0: message segment (feature), 1: string (found version), 2: string (expected version)
+compiler.misc.feature.not.supported.in.source=\
+   {0} is not supported in -source {1}\n\
+    (use -source {2} or higher to enable {0})
+
+# 0: message segment (feature), 1: string (found version), 2: string (expected version)
+compiler.misc.feature.not.supported.in.source.plural=\
+   {0} are not supported in -source {1}\n\
+    (use -source {2} or higher to enable {0})
+
+compiler.misc.feature.modules=\
+    modules
+
+compiler.misc.feature.diamond.and.anon.class=\
+    ''<>'' with anonymous inner classes
+
+compiler.misc.feature.binary.lit=\
+    binary literals
+
+compiler.misc.feature.underscore.lit=\
+    underscores in literals
+
+compiler.misc.feature.try.with.resources=\
+    try-with-resources
+
+compiler.misc.feature.var.in.try.with.resources=\
+    variables in try-with-resources
+
+compiler.misc.feature.type.annotations=\
+    type annotations
+
+compiler.misc.feature.annotations.after.type.params=\
+    annotations after method type parameters
+
+compiler.misc.feature.repeatable.annotations=\
+    repeated annotations
+
+compiler.misc.feature.diamond=\
+    diamond operator
+
+compiler.misc.feature.multicatch=\
+    multi-catch statements
+
+compiler.misc.feature.string.switch=\
+    strings in switch
+
+compiler.misc.feature.lambda=\
+    lambda expressions
+
+compiler.misc.feature.method.references=\
+    method references
+
+compiler.misc.feature.default.methods=\
+    default methods
+
+compiler.misc.feature.intersection.types.in.cast=\
+    intersection types
+
+compiler.misc.feature.static.intf.methods=\
+    static interface methods
+
+compiler.misc.feature.static.intf.method.invoke=\
+    static interface method invocations
+
+compiler.misc.feature.private.intf.methods=\
+    private interface methods
 
 compiler.warn.underscore.as.identifier=\
     as of release 9, ''_'' is a keyword, and may not be used as an identifier
@@ -2694,71 +2743,6 @@
 compiler.err.no.annotations.on.dot.class=\
     no annotations are allowed in the type of a class literal
 
-# 0: string
-compiler.err.type.annotations.not.supported.in.source=\
-    type annotations are not supported in -source {0}\n\
-(use -source 8 or higher to enable type annotations)
-
-# 0: string
-compiler.err.annotations.after.type.params.not.supported.in.source=\
-    annotations after method type parameters are not supported in -source {0}\n\
-(use -source 8 or higher to enable annotations after method type parameters)
-
-# 0: string
-compiler.err.repeatable.annotations.not.supported.in.source=\
-    repeated annotations are not supported in -source {0}\n\
-(use -source 8 or higher to enable repeated annotations)
-
-# 0: string
-compiler.err.diamond.not.supported.in.source=\
-    diamond operator is not supported in -source {0}\n\
-    (use -source 7 or higher to enable diamond operator)
-
-# 0: string
-compiler.err.multicatch.not.supported.in.source=\
-    multi-catch statement is not supported in -source {0}\n\
-    (use -source 7 or higher to enable multi-catch statement)
-
-# 0: string
-compiler.err.string.switch.not.supported.in.source=\
-    strings in switch are not supported in -source {0}\n\
-    (use -source 7 or higher to enable strings in switch)
-
-# 0: string
-compiler.err.lambda.not.supported.in.source=\
-    lambda expressions are not supported in -source {0}\n\
-    (use -source 8 or higher to enable lambda expressions)
-
-# 0: string
-compiler.err.method.references.not.supported.in.source=\
-    method references are not supported in -source {0}\n\
-    (use -source 8 or higher to enable method references)
-
-# 0: string
-compiler.err.default.methods.not.supported.in.source=\
-    default methods are not supported in -source {0}\n\
-    (use -source 8 or higher to enable default methods)
-
-# 0: string
-compiler.err.intersection.types.in.cast.not.supported.in.source=\
-    intersection types in cast are not supported in -source {0}\n\
-    (use -source 8 or higher to enable intersection types in cast)
-
-# 0: string
-compiler.err.static.intf.methods.not.supported.in.source=\
-    static interface methods are not supported in -source {0}\n\
-    (use -source 8 or higher to enable static interface methods)
-
-# 0: string
-compiler.err.static.intf.method.invoke.not.supported.in.source=\
-    static interface method invocations are not supported in -source {0}\n\
-    (use -source 8 or higher to enable static interface method invocations)
-
-# 0: string
-compiler.err.private.intf.methods.not.supported.in.source=\
-    private interface methods are not supported in -source {0}\n\
-    (use -source 9 or higher to enable private interface methods)
-
 ########################################
 # Diagnostics for verbose resolution
 # used by Resolve (debug only)
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java	Mon Dec 04 17:54:49 2017 +0000
@@ -426,7 +426,7 @@
     /** A set of "not-supported-in-source-X" errors produced so far. This is used to only generate
      *  one such error per file.
      */
-    protected Set<Pair<JavaFileObject, String>>  recordedSourceLevelErrors = new HashSet<>();
+    protected Set<Pair<JavaFileObject, List<String>>>  recordedSourceLevelErrors = new HashSet<>();
 
     public boolean hasDiagnosticListener() {
         return diagListener != null;
@@ -521,13 +521,29 @@
         if (!d.isFlagSet(DiagnosticFlag.SOURCE_LEVEL))
             return true;
 
-        Pair<JavaFileObject, String> coords = new Pair<>(file, d.getCode());
+        Pair<JavaFileObject, List<String>> coords = new Pair<>(file, getCode(d));
         boolean shouldReport = !recordedSourceLevelErrors.contains(coords);
         if (shouldReport)
             recordedSourceLevelErrors.add(coords);
         return shouldReport;
     }
 
+    //where
+        private List<String> getCode(JCDiagnostic d) {
+            ListBuffer<String> buf = new ListBuffer<>();
+            getCodeRecursive(buf, d);
+            return buf.toList();
+        }
+
+        private void getCodeRecursive(ListBuffer<String> buf, JCDiagnostic d) {
+            buf.add(d.getCode());
+            for (Object o : d.getArgs()) {
+                if (o instanceof JCDiagnostic) {
+                    getCodeRecursive(buf, (JCDiagnostic)o);
+                }
+            }
+        }
+
     /** Prompt user after an error.
      */
     public void prompt() {
--- a/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/RootDocImpl.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/RootDocImpl.java	Mon Dec 04 17:54:49 2017 +0000
@@ -34,6 +34,7 @@
 import javax.tools.StandardJavaFileManager;
 
 import com.sun.javadoc.*;
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.tree.JCTree.JCClassDecl;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.ListBuffer;
@@ -388,7 +389,7 @@
     }
 
     public boolean isFunctionalInterface(AnnotationDesc annotationDesc) {
-        return env.source.allowLambda()
+        return Feature.LAMBDA.allowedInSource(env.source)
             && annotationDesc.annotationType().qualifiedName().equals(
                 env.syms.functionalInterfaceType.toString());
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java	Mon Dec 04 17:54:49 2017 +0000
@@ -55,6 +55,7 @@
 import com.sun.tools.javac.code.Attribute;
 import com.sun.tools.javac.code.Flags;
 import com.sun.tools.javac.code.Scope;
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
@@ -187,7 +188,7 @@
     // TODO: we need ElementUtils.getPackage to cope with input strings
     // to return the proper unnamedPackage for all supported releases.
     PackageElement getUnnamedPackage() {
-        return (toolEnv.source.allowModules())
+        return (Feature.MODULES.allowedInSource(toolEnv.source))
                 ? toolEnv.syms.unnamedModule.unnamedPackage
                 : toolEnv.syms.noModule.unnamedPackage;
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java	Mon Dec 04 17:54:49 2017 +0000
@@ -55,6 +55,7 @@
 
 import com.sun.tools.javac.code.Kinds.Kind;
 import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.CompletionFailure;
@@ -222,7 +223,7 @@
             else
                 locs.add(StandardLocation.CLASS_PATH);
         }
-        if (source.allowModules() && toolEnv.fileManager.hasLocation(StandardLocation.PATCH_MODULE_PATH))
+        if (Feature.MODULES.allowedInSource(source) && toolEnv.fileManager.hasLocation(StandardLocation.PATCH_MODULE_PATH))
             locs.add(StandardLocation.PATCH_MODULE_PATH);
         this.locations = Collections.unmodifiableList(locs);
 
--- a/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java	Mon Dec 04 17:54:49 2017 +0000
@@ -34,6 +34,7 @@
 import com.sun.tools.javac.util.JCDiagnostic;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import com.sun.tools.javac.util.JCDiagnostic.Error;
 import com.sun.tools.javac.util.Log;
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -78,7 +79,7 @@
         Context context = new Context();
         Log log = CaLog.createLog(context);
         context.put(Log.class, log);
-        context.put(Source.class, Source.JDK1_9);
+        context.put(Source.class, Source.JDK9);
         scannerFactory = ScannerFactory.instance(context);
     }
 
@@ -138,6 +139,11 @@
         }
 
         @Override
+        public void error(int pos, Error errorKey) {
+            die();
+        }
+
+        @Override
         public void error(int pos, String key, Object... args) {
             die();
         }
--- a/src/jdk.jshell/share/classes/jdk/jshell/ReplParser.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/src/jdk.jshell/share/classes/jdk/jshell/ReplParser.java	Mon Dec 04 17:54:49 2017 +0000
@@ -25,6 +25,7 @@
 
 package jdk.jshell;
 
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.code.TypeTag;
 import com.sun.tools.javac.parser.JavacParser;
 import com.sun.tools.javac.parser.ParserFactory;
@@ -191,7 +192,7 @@
                     List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION);
 
                     if (annosAfterParams.nonEmpty()) {
-                        checkAnnotationsAfterTypeParams(annosAfterParams.head.pos);
+                        checkSourceLevel(annosAfterParams.head.pos, Feature.ANNOTATIONS_AFTER_TYPE_PARAMS);
                         mods.annotations = mods.annotations.appendList(annosAfterParams);
                         if (mods.pos == Position.NOPOS) {
                             mods.pos = mods.annotations.head.pos;
--- a/test/langtools/jdk/jshell/CompilerOptionsTest.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/jdk/jshell/CompilerOptionsTest.java	Mon Dec 04 17:54:49 2017 +0000
@@ -51,6 +51,6 @@
     public void testSourceVersion() {
         assertEval("import java.util.function.*;", added(VALID));
         assertDeclareFail("Function<Integer,Integer> f = x -> x*2;",
-                new ExpectedDiagnostic("compiler.err.lambda.not.supported.in.source", 32, 32, 32, -1, -1, Diagnostic.Kind.ERROR));
+                new ExpectedDiagnostic("compiler.err.feature.not.supported.in.source.plural", 32, 32, 32, -1, -1, Diagnostic.Kind.ERROR));
     }
 }
--- a/test/langtools/tools/javac/StringsInSwitch/BadlyTypedLabel1_6.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/StringsInSwitch/BadlyTypedLabel1_6.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,7 +1,7 @@
-- compiler.warn.source.no.bootclasspath: 1.6
-- compiler.warn.option.obsolete.source: 1.6
+- compiler.warn.source.no.bootclasspath: 6
+- compiler.warn.option.obsolete.source: 6
 - compiler.warn.option.obsolete.suppression
-BadlyTypedLabel1.java:10:15: compiler.err.string.switch.not.supported.in.source: 1.6
+BadlyTypedLabel1.java:10:15: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.string.switch), 6, 7
 BadlyTypedLabel1.java:13:14: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: int, java.lang.String)
 2 errors
 3 warnings
--- a/test/langtools/tools/javac/StringsInSwitch/BadlyTypedLabel2_6.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/StringsInSwitch/BadlyTypedLabel2_6.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,7 +1,7 @@
-- compiler.warn.source.no.bootclasspath: 1.6
-- compiler.warn.option.obsolete.source: 1.6
+- compiler.warn.source.no.bootclasspath: 6
+- compiler.warn.option.obsolete.source: 6
 - compiler.warn.option.obsolete.suppression
-BadlyTypedLabel2.java:12:15: compiler.err.string.switch.not.supported.in.source: 1.6
+BadlyTypedLabel2.java:12:15: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.string.switch), 6, 7
 BadlyTypedLabel2.java:15:14: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.math.RoundingMode, java.lang.String)
 2 errors
 3 warnings
--- a/test/langtools/tools/javac/StringsInSwitch/NonConstantLabel6.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/StringsInSwitch/NonConstantLabel6.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,7 +1,7 @@
-- compiler.warn.source.no.bootclasspath: 1.6
-- compiler.warn.option.obsolete.source: 1.6
+- compiler.warn.source.no.bootclasspath: 6
+- compiler.warn.option.obsolete.source: 6
 - compiler.warn.option.obsolete.suppression
-NonConstantLabel.java:11:15: compiler.err.string.switch.not.supported.in.source: 1.6
+NonConstantLabel.java:11:15: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.string.switch), 6, 7
 NonConstantLabel.java:14:14: compiler.err.string.const.req
 2 errors
 3 warnings
--- a/test/langtools/tools/javac/StringsInSwitch/OneCaseSwitches.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/StringsInSwitch/OneCaseSwitches.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,6 +1,6 @@
-- compiler.warn.source.no.bootclasspath: 1.6
-- compiler.warn.option.obsolete.source: 1.6
+- compiler.warn.source.no.bootclasspath: 6
+- compiler.warn.option.obsolete.source: 6
 - compiler.warn.option.obsolete.suppression
-OneCaseSwitches.java:23:15: compiler.err.string.switch.not.supported.in.source: 1.6
+OneCaseSwitches.java:23:15: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.string.switch), 6, 7
 1 error
-3 warnings
\ No newline at end of file
+3 warnings
--- a/test/langtools/tools/javac/StringsInSwitch/RSCL1_6.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/StringsInSwitch/RSCL1_6.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,7 +1,7 @@
-- compiler.warn.source.no.bootclasspath: 1.6
-- compiler.warn.option.obsolete.source: 1.6
+- compiler.warn.source.no.bootclasspath: 6
+- compiler.warn.option.obsolete.source: 6
 - compiler.warn.option.obsolete.suppression
-RepeatedStringCaseLabels1.java:10:15: compiler.err.string.switch.not.supported.in.source: 1.6
+RepeatedStringCaseLabels1.java:10:15: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.string.switch), 6, 7
 RepeatedStringCaseLabels1.java:13:9: compiler.err.duplicate.case.label
 2 errors
 3 warnings
--- a/test/langtools/tools/javac/StringsInSwitch/RSCL2_6.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/StringsInSwitch/RSCL2_6.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,7 +1,7 @@
-- compiler.warn.source.no.bootclasspath: 1.6
-- compiler.warn.option.obsolete.source: 1.6
+- compiler.warn.source.no.bootclasspath: 6
+- compiler.warn.option.obsolete.source: 6
 - compiler.warn.option.obsolete.suppression
-RepeatedStringCaseLabels2.java:11:15: compiler.err.string.switch.not.supported.in.source: 1.6
+RepeatedStringCaseLabels2.java:11:15: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.string.switch), 6, 7
 RepeatedStringCaseLabels2.java:14:9: compiler.err.duplicate.case.label
 2 errors
 3 warnings
--- a/test/langtools/tools/javac/TryWithResources/BadTwr6.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/TryWithResources/BadTwr6.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,6 +1,6 @@
-- compiler.warn.source.no.bootclasspath: 1.6
-- compiler.warn.option.obsolete.source: 1.6
+- compiler.warn.source.no.bootclasspath: 6
+- compiler.warn.option.obsolete.source: 6
 - compiler.warn.option.obsolete.suppression
-BadTwr.java:13:12: compiler.err.try.with.resources.not.supported.in.source: 1.6
+BadTwr.java:13:12: compiler.err.feature.not.supported.in.source: (compiler.misc.feature.try.with.resources), 6, 7
 1 error
 3 warnings
--- a/test/langtools/tools/javac/TryWithResources/BadTwrSyntax6.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/TryWithResources/BadTwrSyntax6.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,7 +1,7 @@
-- compiler.warn.source.no.bootclasspath: 1.6
-- compiler.warn.option.obsolete.source: 1.6
+- compiler.warn.source.no.bootclasspath: 6
+- compiler.warn.option.obsolete.source: 6
 - compiler.warn.option.obsolete.suppression
-BadTwrSyntax.java:14:12: compiler.err.try.with.resources.not.supported.in.source: 1.6
+BadTwrSyntax.java:14:12: compiler.err.feature.not.supported.in.source: (compiler.misc.feature.try.with.resources), 6, 7
 BadTwrSyntax.java:14:43: compiler.err.illegal.start.of.expr
 2 errors
 3 warnings
--- a/test/langtools/tools/javac/TryWithResources/TwrForVariable1.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/TryWithResources/TwrForVariable1.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,2 +1,2 @@
-TwrForVariable1.java:13:14: compiler.err.var.in.try.with.resources.not.supported.in.source: 1.8
+TwrForVariable1.java:13:15: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.var.in.try.with.resources), 8, 9
 1 error
--- a/test/langtools/tools/javac/TryWithResources/TwrOnNonResource6.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/TryWithResources/TwrOnNonResource6.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,6 +1,6 @@
-- compiler.warn.source.no.bootclasspath: 1.6
-- compiler.warn.option.obsolete.source: 1.6
+- compiler.warn.source.no.bootclasspath: 6
+- compiler.warn.option.obsolete.source: 6
 - compiler.warn.option.obsolete.suppression
-TwrOnNonResource.java:12:12: compiler.err.try.with.resources.not.supported.in.source: 1.6
+TwrOnNonResource.java:12:12: compiler.err.feature.not.supported.in.source: (compiler.misc.feature.try.with.resources), 6, 7
 1 error
 3 warnings
--- a/test/langtools/tools/javac/TryWithResources/WeirdTwr.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/TryWithResources/WeirdTwr.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,6 +1,6 @@
-- compiler.warn.source.no.bootclasspath: 1.6
-- compiler.warn.option.obsolete.source: 1.6
+- compiler.warn.source.no.bootclasspath: 6
+- compiler.warn.option.obsolete.source: 6
 - compiler.warn.option.obsolete.suppression
-WeirdTwr.java:14:12: compiler.err.try.with.resources.not.supported.in.source: 1.6
+WeirdTwr.java:14:12: compiler.err.feature.not.supported.in.source: (compiler.misc.feature.try.with.resources), 6, 7
 1 error
 3 warnings
--- a/test/langtools/tools/javac/annotations/repeatingAnnotations/WrongVersion6.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/annotations/repeatingAnnotations/WrongVersion6.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,2 +1,2 @@
-WrongVersion.java:12:9: compiler.err.repeatable.annotations.not.supported.in.source: 1.6
+WrongVersion.java:12:9: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.repeatable.annotations), 6, 8
 1 error
--- a/test/langtools/tools/javac/annotations/repeatingAnnotations/WrongVersion7.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/annotations/repeatingAnnotations/WrongVersion7.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,2 +1,2 @@
-WrongVersion.java:12:9: compiler.err.repeatable.annotations.not.supported.in.source: 1.7
+WrongVersion.java:12:9: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.repeatable.annotations), 7, 8
 1 error
--- a/test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,2 +1,2 @@
-AnnotationVersion.java:12:27: compiler.err.type.annotations.not.supported.in.source: 1.6
+AnnotationVersion.java:12:27: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.type.annotations), 6, 8
 1 error
--- a/test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion7.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion7.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,2 +1,2 @@
-AnnotationVersion.java:12:27: compiler.err.type.annotations.not.supported.in.source: 1.7
+AnnotationVersion.java:12:27: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.type.annotations), 7, 8
 1 error
--- a/test/langtools/tools/javac/annotations/typeAnnotations/failures/CheckErrorsForSource7.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/annotations/typeAnnotations/failures/CheckErrorsForSource7.java	Mon Dec 04 17:54:49 2017 +0000
@@ -135,7 +135,7 @@
                 boolean found = false;
 
                 for (Diagnostic<? extends JavaFileObject> d : errors.getDiagnostics()) {
-                    if (d.getKind() == Diagnostic.Kind.ERROR && EXPECTED_ERRORS.contains(d.getCode())) {
+                    if (d.getKind() == Diagnostic.Kind.ERROR && EXPECTED_ERROR.equals(d.getCode())) {
                         if (found) {
                             throw new IllegalStateException("More than one expected error found.");
                         }
@@ -149,10 +149,7 @@
         }
     }
 
-    static final Set<String> EXPECTED_ERRORS = new HashSet<>(Arrays.asList(
-        "compiler.err.type.annotations.not.supported.in.source",
-        "compiler.err.annotations.after.type.params.not.supported.in.source"
-    ));
+    static final String EXPECTED_ERROR = "compiler.err.feature.not.supported.in.source.plural";
 
     class TestFO extends SimpleJavaFileObject {
         private final String content;
--- a/test/langtools/tools/javac/conditional/Conditional.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/conditional/Conditional.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,4 +1,4 @@
-- compiler.warn.source.no.bootclasspath: 1.7
+- compiler.warn.source.no.bootclasspath: 7
 Conditional.java:16:38: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.util.List<? extends java.lang.Object>, java.util.List<java.lang.String>)
 1 error
 1 warning
--- a/test/langtools/tools/javac/defaultMethods/static/StaticInvokeQualified6.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/defaultMethods/static/StaticInvokeQualified6.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,2 +1,2 @@
-StaticInvokeQualified.java:11:32: compiler.err.static.intf.method.invoke.not.supported.in.source: 1.6
+StaticInvokeQualified.java:11:32: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.static.intf.method.invoke), 6, 8
 1 error
--- a/test/langtools/tools/javac/defaultMethods/static/StaticInvokeQualified7.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/defaultMethods/static/StaticInvokeQualified7.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,2 +1,2 @@
-StaticInvokeQualified.java:11:32: compiler.err.static.intf.method.invoke.not.supported.in.source: 1.7
+StaticInvokeQualified.java:11:32: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.static.intf.method.invoke), 7, 8
 1 error
--- a/test/langtools/tools/javac/defaultMethods/static/StaticInvokeSimple6.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/defaultMethods/static/StaticInvokeSimple6.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,2 +1,2 @@
-StaticInvokeSimple.java:12:15: compiler.err.static.intf.method.invoke.not.supported.in.source: 1.6
+StaticInvokeSimple.java:12:15: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.static.intf.method.invoke), 6, 8
 1 error
--- a/test/langtools/tools/javac/defaultMethods/static/StaticInvokeSimple7.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/defaultMethods/static/StaticInvokeSimple7.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,2 +1,2 @@
-StaticInvokeSimple.java:12:15: compiler.err.static.intf.method.invoke.not.supported.in.source: 1.7
-1 error
\ No newline at end of file
+StaticInvokeSimple.java:12:15: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.static.intf.method.invoke), 7, 8
+1 error
--- a/test/langtools/tools/javac/depDocComment/SuppressDeprecation8.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/depDocComment/SuppressDeprecation8.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,4 +1,4 @@
-- compiler.warn.source.no.bootclasspath: 1.8
+- compiler.warn.source.no.bootclasspath: 8
 SuppressDeprecation.java:83:10: compiler.warn.has.been.deprecated: g(), T
 SuppressDeprecation.java:84:14: compiler.warn.has.been.deprecated: g(), T
 SuppressDeprecation.java:85:9: compiler.warn.has.been.deprecated: var, T
--- a/test/langtools/tools/javac/diags/examples.not-yet.txt	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples.not-yet.txt	Mon Dec 04 17:54:49 2017 +0000
@@ -61,6 +61,7 @@
 compiler.misc.fatal.err.cant.locate.field               # Resolve, from Lower
 compiler.misc.fatal.err.cant.locate.meth                # Resolve, from Lower
 compiler.misc.fatal.err.cant.close	                # JavaCompiler
+compiler.misc.feature.not.supported.in.source.plural    # cannot happen (for now)
 compiler.misc.file.does.not.contain.package
 compiler.misc.illegal.start.of.class.file
 compiler.misc.inferred.do.not.conform.to.lower.bounds   # cannot happen?
--- a/test/langtools/tools/javac/diags/examples/AnnotationsAfterTypeParamsNotSupportedInSource.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples/AnnotationsAfterTypeParamsNotSupportedInSource.java	Mon Dec 04 17:54:49 2017 +0000
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// key: compiler.err.annotations.after.type.params.not.supported.in.source
+// key: compiler.err.feature.not.supported.in.source.plural
+// key: compiler.misc.feature.annotations.after.type.params
 // key: compiler.warn.source.no.bootclasspath
 // options: -source 7
 
--- a/test/langtools/tools/javac/diags/examples/DefaultMethodNotSupported.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples/DefaultMethodNotSupported.java	Mon Dec 04 17:54:49 2017 +0000
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// key: compiler.err.default.methods.not.supported.in.source
+// key: compiler.err.feature.not.supported.in.source.plural
+// key: compiler.misc.feature.default.methods
 // options: -source 7 -Xlint:-options
 
 interface DefaultMethodNotSupported {
--- a/test/langtools/tools/javac/diags/examples/DiamondAndAnonClass.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples/DiamondAndAnonClass.java	Mon Dec 04 17:54:49 2017 +0000
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// key: compiler.misc.diamond.and.anon.class.not.supported.in.source
+// key: compiler.misc.feature.not.supported.in.source
+// key: compiler.misc.feature.diamond.and.anon.class
 // key: compiler.err.cant.apply.diamond.1
 // key: compiler.warn.source.no.bootclasspath
 // options: -source 8
--- a/test/langtools/tools/javac/diags/examples/DiamondNotSupported.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples/DiamondNotSupported.java	Mon Dec 04 17:54:49 2017 +0000
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// key: compiler.err.diamond.not.supported.in.source
+// key: compiler.err.feature.not.supported.in.source
+// key: compiler.misc.feature.diamond
 // options: -source 6 -Xlint:-options
 
 import java.util.*;
--- a/test/langtools/tools/javac/diags/examples/IntersectionTypesInCastNotSupported.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples/IntersectionTypesInCastNotSupported.java	Mon Dec 04 17:54:49 2017 +0000
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// key: compiler.err.intersection.types.in.cast.not.supported.in.source
+// key: compiler.err.feature.not.supported.in.source.plural
+// key: compiler.misc.feature.intersection.types.in.cast
 // options: -source 7 -Xlint:-options
 
 interface IntersectionTypesInCastNotSupported {
--- a/test/langtools/tools/javac/diags/examples/LambdaNotSupported.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples/LambdaNotSupported.java	Mon Dec 04 17:54:49 2017 +0000
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// key: compiler.err.lambda.not.supported.in.source
+// key: compiler.err.feature.not.supported.in.source.plural
+// key: compiler.misc.feature.lambda
 // options: -source 7 -Xlint:-options
 
 class LambdaNotSupported {
--- a/test/langtools/tools/javac/diags/examples/MethodReferencesNotSupported.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples/MethodReferencesNotSupported.java	Mon Dec 04 17:54:49 2017 +0000
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// key: compiler.err.method.references.not.supported.in.source
+// key: compiler.err.feature.not.supported.in.source.plural
+// key: compiler.misc.feature.method.references
 // options: -source 7 -Xlint:-options
 
 class MethodReferencesNotSupported {
--- a/test/langtools/tools/javac/diags/examples/ModulesNotSupportedInSource/module-info.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples/ModulesNotSupportedInSource/module-info.java	Mon Dec 04 17:54:49 2017 +0000
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// key: compiler.err.modules.not.supported.in.source
+// key: compiler.err.feature.not.supported.in.source.plural
+// key: compiler.misc.feature.modules
 // key: compiler.warn.source.no.bootclasspath
 // options: -source 8 -Xlint:-path
 
--- a/test/langtools/tools/javac/diags/examples/MulticatchNotSupported.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples/MulticatchNotSupported.java	Mon Dec 04 17:54:49 2017 +0000
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// key: compiler.err.multicatch.not.supported.in.source
+// key: compiler.err.feature.not.supported.in.source.plural
+// key: compiler.misc.feature.multicatch
 // options: -source 1.6 -Xlint:-options
 
 class MulticatchNotSupported {
--- a/test/langtools/tools/javac/diags/examples/PrivateInterfaceMethodsNotSupported.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples/PrivateInterfaceMethodsNotSupported.java	Mon Dec 04 17:54:49 2017 +0000
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// key: compiler.err.private.intf.methods.not.supported.in.source
+// key: compiler.err.feature.not.supported.in.source.plural
+// key: compiler.misc.feature.private.intf.methods
 // key: compiler.warn.source.no.bootclasspath
 // options: -source 8
 
--- a/test/langtools/tools/javac/diags/examples/RepeatableAnnotationsNotSupported.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples/RepeatableAnnotationsNotSupported.java	Mon Dec 04 17:54:49 2017 +0000
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// key: compiler.err.repeatable.annotations.not.supported.in.source
+// key: compiler.err.feature.not.supported.in.source.plural
+// key: compiler.misc.feature.repeatable.annotations
 // key: compiler.warn.source.no.bootclasspath
 // options: -source 7
 
--- a/test/langtools/tools/javac/diags/examples/StaticIntfMethodInvokeNotSupported.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples/StaticIntfMethodInvokeNotSupported.java	Mon Dec 04 17:54:49 2017 +0000
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// key: compiler.err.static.intf.method.invoke.not.supported.in.source
+// key: compiler.err.feature.not.supported.in.source.plural
+// key: compiler.misc.feature.static.intf.method.invoke
 // options: -source 7 -Xlint:-options
 import java.util.stream.Stream;
 
--- a/test/langtools/tools/javac/diags/examples/StaticIntfMethodNotSupported.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples/StaticIntfMethodNotSupported.java	Mon Dec 04 17:54:49 2017 +0000
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// key: compiler.err.static.intf.methods.not.supported.in.source
+// key: compiler.err.feature.not.supported.in.source.plural
+// key: compiler.misc.feature.static.intf.methods
 // options: -source 7 -Xlint:-options -XDallowStaticInterfaceMethods
 
 interface StaticIntfMethodNotSupported {
--- a/test/langtools/tools/javac/diags/examples/StringSwitchNotSupported.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples/StringSwitchNotSupported.java	Mon Dec 04 17:54:49 2017 +0000
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// key: compiler.err.string.switch.not.supported.in.source
+// key: compiler.err.feature.not.supported.in.source.plural
+// key: compiler.misc.feature.string.switch
 // options: -source 6 -Xlint:-options
 
 class StringSwitchNotSupported {
--- a/test/langtools/tools/javac/diags/examples/TryResourceNotSupported.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples/TryResourceNotSupported.java	Mon Dec 04 17:54:49 2017 +0000
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// key: compiler.err.try.with.resources.not.supported.in.source
+// key: compiler.err.feature.not.supported.in.source
+// key: compiler.misc.feature.try.with.resources
 // options: -source 1.6 -Xlint:-options
 
 import java.io.*;
--- a/test/langtools/tools/javac/diags/examples/TypeAnnotationsNotSupported.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples/TypeAnnotationsNotSupported.java	Mon Dec 04 17:54:49 2017 +0000
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// key: compiler.err.type.annotations.not.supported.in.source
+// key: compiler.err.feature.not.supported.in.source.plural
+// key: compiler.misc.feature.type.annotations
 // key: compiler.warn.source.no.bootclasspath
 // options: -source 7
 
--- a/test/langtools/tools/javac/diags/examples/UnsupportedBinaryLiteral.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples/UnsupportedBinaryLiteral.java	Mon Dec 04 17:54:49 2017 +0000
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// key: compiler.err.unsupported.binary.lit
+// key: compiler.err.feature.not.supported.in.source.plural
+// key: compiler.misc.feature.binary.lit
 // options: -source 6 -Xlint:-options
 
 class UnsupportedBinaryLiteral {
--- a/test/langtools/tools/javac/diags/examples/UnsupportedUnderscoreLiteral.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples/UnsupportedUnderscoreLiteral.java	Mon Dec 04 17:54:49 2017 +0000
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// key: compiler.err.unsupported.underscore.lit
+// key: compiler.err.feature.not.supported.in.source.plural
+// key: compiler.misc.feature.underscore.lit
 // options: -source 6 -Xlint:-options
 
 class UnsupportedUnderscoreLiteral {
--- a/test/langtools/tools/javac/diags/examples/VarInTryWithResourcesNotSupportedInSource.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/diags/examples/VarInTryWithResourcesNotSupportedInSource.java	Mon Dec 04 17:54:49 2017 +0000
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// key: compiler.err.var.in.try.with.resources.not.supported.in.source
+// key: compiler.err.feature.not.supported.in.source.plural
+// key: compiler.misc.feature.var.in.try.with.resources
 // key: compiler.warn.source.no.bootclasspath
 // options: -source 8
 
--- a/test/langtools/tools/javac/generics/diamond/neg/Neg09a.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/generics/diamond/neg/Neg09a.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,4 +1,4 @@
-- compiler.warn.source.no.bootclasspath: 1.8
-Neg09a.java:15:34: compiler.err.cant.apply.diamond.1: Neg09a.Member<X>, (compiler.misc.diamond.and.anon.class.not.supported.in.source: 1.8)
+- compiler.warn.source.no.bootclasspath: 8
+Neg09a.java:15:34: compiler.err.cant.apply.diamond.1: Neg09a.Member<X>, (compiler.misc.feature.not.supported.in.source: (compiler.misc.feature.diamond.and.anon.class), 8, 9)
 1 error
 1 warning
--- a/test/langtools/tools/javac/generics/diamond/neg/Neg09b.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/generics/diamond/neg/Neg09b.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,4 +1,4 @@
-- compiler.warn.source.no.bootclasspath: 1.8
-Neg09b.java:16:34: compiler.err.cant.apply.diamond.1: Neg09b.Nested<X>, (compiler.misc.diamond.and.anon.class.not.supported.in.source: 1.8)
+- compiler.warn.source.no.bootclasspath: 8
+Neg09b.java:16:34: compiler.err.cant.apply.diamond.1: Neg09b.Nested<X>, (compiler.misc.feature.not.supported.in.source: (compiler.misc.feature.diamond.and.anon.class), 8, 9)
 1 error
 1 warning
--- a/test/langtools/tools/javac/generics/diamond/neg/Neg09c.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/generics/diamond/neg/Neg09c.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,4 +1,4 @@
-- compiler.warn.source.no.bootclasspath: 1.8
-Neg09c.java:15:39: compiler.err.cant.apply.diamond.1: Neg09c.Member<X>, (compiler.misc.diamond.and.anon.class.not.supported.in.source: 1.8)
+- compiler.warn.source.no.bootclasspath: 8
+Neg09c.java:15:39: compiler.err.cant.apply.diamond.1: Neg09c.Member<X>, (compiler.misc.feature.not.supported.in.source: (compiler.misc.feature.diamond.and.anon.class), 8, 9)
 1 error
 1 warning
--- a/test/langtools/tools/javac/generics/diamond/neg/Neg09d.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/generics/diamond/neg/Neg09d.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,4 +1,4 @@
-- compiler.warn.source.no.bootclasspath: 1.8
+- compiler.warn.source.no.bootclasspath: 8
 Neg09d.java:16:33: compiler.err.doesnt.exist: Neg09
 1 error
 1 warning
--- a/test/langtools/tools/javac/generics/inference/6278587/T6278587Neg.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/generics/inference/6278587/T6278587Neg.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,4 +1,4 @@
-- compiler.warn.source.no.bootclasspath: 1.7
+- compiler.warn.source.no.bootclasspath: 7
 T6278587Neg.java:18:10: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.lower.bounds: T, T6278587Neg.C)
 1 error
 1 warning
--- a/test/langtools/tools/javac/generics/odersky/BadTest4.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/generics/odersky/BadTest4.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,4 +1,4 @@
-- compiler.warn.source.no.bootclasspath: 1.7
+- compiler.warn.source.no.bootclasspath: 7
 BadTest4.java:38:17: compiler.err.cant.apply.symbol: kindname.method, f, A,B, java.lang.Integer,java.lang.Number, kindname.class, BadTest4.Main, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Number, java.lang.Integer)
 1 error
 1 warning
--- a/test/langtools/tools/javac/lambda/SourceLevelTest.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/lambda/SourceLevelTest.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,6 +1,6 @@
-- compiler.warn.source.no.bootclasspath: 1.7
-SourceLevelTest.java:11:9: compiler.err.default.methods.not.supported.in.source: 1.7
-SourceLevelTest.java:18:17: compiler.err.lambda.not.supported.in.source: 1.7
-SourceLevelTest.java:19:20: compiler.err.method.references.not.supported.in.source: 1.7
+- compiler.warn.source.no.bootclasspath: 7
+SourceLevelTest.java:11:9: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.default.methods), 7, 8
+SourceLevelTest.java:18:17: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.lambda), 7, 8
+SourceLevelTest.java:19:20: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.method.references), 7, 8
 3 errors
 1 warning
--- a/test/langtools/tools/javac/literals/BadBinaryLiterals.6.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/literals/BadBinaryLiterals.6.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,8 +1,6 @@
-BadBinaryLiterals.java:10:17: compiler.err.unsupported.binary.lit: 1.6
+BadBinaryLiterals.java:10:17: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.binary.lit), 6, 7
 BadBinaryLiterals.java:11:24: compiler.err.expected: ';'
-BadBinaryLiterals.java:13:21: compiler.err.int.number.too.large: 111111111111111111111111111111111
-BadBinaryLiterals.java:15:21: compiler.err.int.number.too.large: 11111111111111111111111111111111111111111111111111111111111111111
 BadBinaryLiterals.java:16:27: compiler.err.expected: ';'
 BadBinaryLiterals.java:17:27: compiler.err.expected: ';'
 BadBinaryLiterals.java:17:30: compiler.err.expected: token.identifier
-7 errors
+5 errors
--- a/test/langtools/tools/javac/literals/BadUnderscoreLiterals.6.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/literals/BadUnderscoreLiterals.6.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,7 +1,7 @@
-BadUnderscoreLiterals.java:11:17: compiler.err.unsupported.underscore.lit: 1.6
+BadUnderscoreLiterals.java:11:17: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.underscore.lit), 6, 7
 BadUnderscoreLiterals.java:15:15: compiler.err.illegal.underscore
 BadUnderscoreLiterals.java:19:19: compiler.err.illegal.underscore
-BadUnderscoreLiterals.java:22:14: compiler.err.unsupported.binary.lit: 1.6
+BadUnderscoreLiterals.java:22:14: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.binary.lit), 6, 7
 BadUnderscoreLiterals.java:22:16: compiler.err.illegal.underscore
 BadUnderscoreLiterals.java:23:17: compiler.err.illegal.underscore
 BadUnderscoreLiterals.java:26:16: compiler.err.illegal.underscore
--- a/test/langtools/tools/javac/options/T6900037.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/options/T6900037.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,4 +1,4 @@
-- compiler.warn.source.no.bootclasspath: 1.8
+- compiler.warn.source.no.bootclasspath: 8
 - compiler.err.warnings.and.werror
 1 error
 1 warning
--- a/test/langtools/tools/javac/parser/extend/TrialParser.java	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/parser/extend/TrialParser.java	Mon Dec 04 17:54:49 2017 +0000
@@ -21,6 +21,7 @@
  * questions.
  */
 
+import com.sun.tools.javac.code.Source.Feature;
 import com.sun.tools.javac.code.TypeTag;
 import com.sun.tools.javac.parser.JavacParser;
 import com.sun.tools.javac.parser.ParserFactory;
@@ -186,7 +187,7 @@
                     List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION);
 
                     if (annosAfterParams.nonEmpty()) {
-                        checkAnnotationsAfterTypeParams(annosAfterParams.head.pos);
+                        checkSourceLevel(annosAfterParams.head.pos, Feature.ANNOTATIONS_AFTER_TYPE_PARAMS);
                         mods.annotations = mods.annotations.appendList(annosAfterParams);
                         if (mods.pos == Position.NOPOS) {
                             mods.pos = mods.annotations.head.pos;
--- a/test/langtools/tools/javac/processing/warnings/gold_sv_warn_5_6.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/processing/warnings/gold_sv_warn_5_6.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,2 +1,2 @@
-- compiler.warn.proc.processor.incompatible.source.version: RELEASE_5, TestSourceVersionWarnings, 1.6
+- compiler.warn.proc.processor.incompatible.source.version: RELEASE_5, TestSourceVersionWarnings, 6
 1 warning
--- a/test/langtools/tools/javac/varargs/6313164/T6313164Source7.out	Mon Dec 04 10:13:58 2017 +0100
+++ b/test/langtools/tools/javac/varargs/6313164/T6313164Source7.out	Mon Dec 04 17:54:49 2017 +0000
@@ -1,4 +1,4 @@
-- compiler.warn.source.no.bootclasspath: 1.7
+- compiler.warn.source.no.bootclasspath: 7
 T6313164.java:14:10: compiler.err.cant.apply.symbol: kindname.method, foo1, p1.A[], p1.B,p1.B, kindname.class, p1.B, (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164)
 T6313164.java:19:15: compiler.err.prob.found.req: (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164)
 T6313164.java:20:15: compiler.err.prob.found.req: (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164)