1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.javac.code; 27 28 import com.sun.tools.javac.code.Lint.LintCategory; 29 import com.sun.tools.javac.code.Source.Feature; 30 import com.sun.tools.javac.comp.Infer; 31 import com.sun.tools.javac.jvm.Target; 32 import com.sun.tools.javac.resources.CompilerProperties.Errors; 33 import com.sun.tools.javac.resources.CompilerProperties.Warnings; 34 import com.sun.tools.javac.util.Assert; 35 import com.sun.tools.javac.util.Context; 36 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 37 import com.sun.tools.javac.util.JCDiagnostic.Error; 38 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition; 39 import com.sun.tools.javac.util.Log; 40 import com.sun.tools.javac.util.MandatoryWarningHandler; 41 import com.sun.tools.javac.util.Name; 42 import com.sun.tools.javac.util.Options; 43 44 import javax.tools.JavaFileObject; 45 import java.util.HashMap; 46 import java.util.HashSet; 47 import java.util.Map; 48 import java.util.Optional; 49 import java.util.Set; 50 51 import static com.sun.tools.javac.main.Option.PREVIEW; 52 53 /** 54 * Helper class to handle preview language features. This class maps certain language features 55 * (see {@link Feature} into 'preview' features; the mapping is completely ad-hoc, so as to allow 56 * for maximum flexibility, which allows to migrate preview feature into supported features with ease. 57 * 58 * This class acts as a centralized point against which usages of preview features are reported by 59 * clients (e.g. other javac classes). Internally, this class collects all such usages and generates 60 * diagnostics to inform the user of such usages. Such diagnostics can be enabled using the 61 * {@link LintCategory#PREVIEW} lint category, and are suppressible by usual means. 62 */ 63 public class Preview { 64 65 /** flag: are preview featutres enabled */ 66 private final boolean enabled; 67 68 /** the diag handler to manage preview feature usage diagnostics */ 69 private final MandatoryWarningHandler previewHandler; 70 71 /** test flag: should all features be considered as preview features? */ 72 private final boolean forcePreview; 73 74 /** a mapping from classfile numbers to Java SE versions */ 75 private final Map<Integer, Source> majorVersionToSource; 76 77 78 private final Lint lint; 79 private final Log log; 80 81 private static final Context.Key<Preview> previewKey = new Context.Key<>(); 82 83 public static Preview instance(Context context) { 84 Preview instance = context.get(previewKey); 85 if (instance == null) { 86 instance = new Preview(context); 87 } 88 return instance; 89 } 90 91 Preview(Context context) { 92 context.put(previewKey, this); 93 Options options = Options.instance(context); 94 enabled = options.isSet(PREVIEW); 95 log = Log.instance(context); 96 lint = Lint.instance(context); 97 this.previewHandler = 98 new MandatoryWarningHandler(log, lint.isEnabled(LintCategory.PREVIEW), true, "preview", LintCategory.PREVIEW); 99 forcePreview = options.isSet("forcePreview"); 100 majorVersionToSource = initMajorVersionToSourceMap(); 101 } 102 103 private Map<Integer, Source> initMajorVersionToSourceMap() { 104 Map<Integer, Source> majorVersionToSource = new HashMap<>(); 105 for (Target t : Target.values()) { 106 int major = t.majorVersion; 107 Source source = Source.lookup(t.name); 108 if (source != null) { 109 majorVersionToSource.put(major, source); 110 } 111 } 112 return majorVersionToSource; 113 } 114 115 /** 116 * Report usage of a preview feature. Usages reported through this method will affect the 117 * set of sourcefiles with dependencies on preview features. 118 * @param pos the position at which the preview feature was used. 119 * @param feature the preview feature used. 120 */ 121 public void warnPreview(int pos, Feature feature) { 122 warnPreview(new SimpleDiagnosticPosition(pos), feature); 123 } 124 125 /** 126 * Report usage of a preview feature. Usages reported through this method will affect the 127 * set of sourcefiles with dependencies on preview features. 128 * @param pos the position at which the preview feature was used. 129 * @param feature the preview feature used. 130 */ 131 public void warnPreview(DiagnosticPosition pos, Feature feature) { 132 Assert.check(isEnabled()); 133 Assert.check(isPreview(feature)); 134 if (!lint.isSuppressed(LintCategory.PREVIEW)) { 135 previewHandler.report(pos, feature.isPlural() ? 136 Warnings.PreviewFeatureUsePlural(feature.nameFragment()) : 137 Warnings.PreviewFeatureUse(feature.nameFragment())); 138 } 139 } 140 141 /** 142 * Report usage of a preview feature in classfile. 143 * @param classfile the name of the classfile with preview features enabled 144 * @param majorVersion the major version found in the classfile. 145 */ 146 public void warnPreview(JavaFileObject classfile, int majorVersion) { 147 Assert.check(isEnabled()); 148 if (!lint.isSuppressed(LintCategory.PREVIEW)) { 149 previewHandler.report(null, 150 Warnings.PreviewFeatureUseClassfile(classfile, majorVersionToSource.get(majorVersion).name)); 151 } 152 } 153 154 /** 155 * Are preview features enabled? 156 * @return true, if preview features are enabled. 157 */ 158 public boolean isEnabled() { 159 return enabled; 160 } 161 162 /** 163 * Is given feature a preview feature? 164 * @param feature the feature to be tested. 165 * @return true, if given feature is a preview feature. 166 */ 167 public boolean isPreview(Feature feature) { 168 //Note: this is a backdoor which allows to optionally treat all features as 'preview' (for testing). 169 //When real preview features will be added, this method can be implemented to return 'true' 170 //for those selected features, and 'false' for all the others. 171 return forcePreview; 172 } 173 174 /** 175 * Generate an error key which captures the fact that a given preview feature could not be used 176 * due to the preview feature support being disabled. 177 * @param feature the feature for which the diagnostic has to be generated. 178 * @return the diagnostic. 179 */ 180 public Error disabledError(Feature feature) { 181 Assert.check(!isEnabled()); 182 return feature.isPlural() ? 183 Errors.PreviewFeatureDisabledPlural(feature.nameFragment()) : 184 Errors.PreviewFeatureDisabled(feature.nameFragment()); 185 } 186 187 /** 188 * Generate an error key which captures the fact that a preview classfile cannot be loaded 189 * due to the preview feature support being disabled. 190 * @param classfile the name of the classfile with preview features enabled 191 * @param majorVersion the major version found in the classfile. 192 */ 193 public Error disabledError(JavaFileObject classfile, int majorVersion) { 194 Assert.check(!isEnabled()); 195 return Errors.PreviewFeatureDisabledClassfile(classfile, majorVersionToSource.get(majorVersion).name); 196 } 197 198 /** 199 * Report any deferred diagnostics. 200 */ 201 public void reportDeferredDiagnostics() { 202 previewHandler.reportDeferredDiagnostic(); 203 } 204 }