diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java index f3749677b9e..db8b855eb72 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java @@ -73,7 +73,7 @@ import jdk.javadoc.internal.doclets.toolkit.util.Utils.Pair; import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberCache; import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable; import jdk.javadoc.internal.doclint.DocLint; -import jdk.javadoc.internal.doclint.Env; +import jdk.javadoc.internal.tool.AccessLevel; /** * Configure the output based on the options. Doclets should subclass @@ -654,10 +654,10 @@ public abstract class BaseConfiguration { private boolean isDocLintGroupEnabled(jdk.javadoc.internal.doclint.Messages.Group group) { // Use AccessKind.PUBLIC as a stand-in, since it is not common to - // set DocLint options per access kind (as is common with javac.) - // A more sophisticated solution might be to derive the access kind from the + // set DocLint options per access level (as is common with javac.) + // A more sophisticated solution might be to derive the access level from the // element owning the comment, and its enclosing elements. - return doclint != null && doclint.isGroupEnabled(group, Env.AccessKind.PUBLIC); + return doclint != null && doclint.isGroupEnabled(group, AccessLevel.PUBLIC); } //</editor-fold> } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/DocLint.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/DocLint.java index 0139f95b74b..9767eff0dd6 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/DocLint.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/DocLint.java @@ -64,6 +64,7 @@ import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.DefinedBy; import com.sun.tools.javac.util.DefinedBy.Api; import com.sun.tools.javac.util.StringUtils.DamerauLevenshteinDistance; +import jdk.javadoc.internal.tool.AccessLevel; /** * Multi-function entry point for the doc check utility. @@ -410,8 +411,8 @@ public class DocLint extends com.sun.tools.doclint.DocLint { return false; } - public boolean isGroupEnabled(Messages.Group group, Env.AccessKind accessKind) { - return env.messages.isEnabled(group, accessKind); + public boolean isGroupEnabled(Messages.Group group, AccessLevel accessLevel) { + return env.messages.isEnabled(group, accessLevel); } private String localize(String code, Object... args) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Env.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Env.java index aa88ccd981c..f576da1d485 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Env.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Env.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,38 +62,13 @@ import com.sun.tools.javac.model.JavacTypes; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.util.MatchingUtils; import com.sun.tools.javac.util.StringUtils; +import jdk.javadoc.internal.tool.AccessLevel; /** * Utility container for current execution environment, * providing the current declaration and its doc comment. */ public class Env { - /** - * Access kinds for declarations. - */ - public enum AccessKind { - PRIVATE, - PACKAGE, - PROTECTED, - PUBLIC; - - static boolean accepts(String opt) { - for (AccessKind g: values()) - if (opt.equals(StringUtils.toLowerCase(g.name()))) return true; - return false; - } - - static AccessKind of(Set<Modifier> mods) { - if (mods.contains(Modifier.PUBLIC)) - return AccessKind.PUBLIC; - else if (mods.contains(Modifier.PROTECTED)) - return AccessKind.PROTECTED; - else if (mods.contains(Modifier.PRIVATE)) - return AccessKind.PRIVATE; - else - return AccessKind.PACKAGE; - } - } /** Message handler. */ final Messages messages; @@ -136,12 +111,12 @@ public class Env { /** The comment current being analyzed. */ DocCommentTree currDocComment; /** - * The access kind of the declaration containing the comment currently being analyzed. - * This is the minimum (most restrictive) access kind of the declaration itself + * The access level of the declaration containing the comment currently being analyzed. + * This is the most limiting access level of the declaration itself * and that of its containers. For example, a public method in a private class is * noted as private. */ - AccessKind currAccess; + AccessLevel currAccess; /** The set of methods, if any, that the current declaration overrides. */ Set<? extends ExecutableElement> currOverriddenMethods; @@ -219,18 +194,18 @@ public class Env { currElement = trees.getElement(currPath); currOverriddenMethods = ((JavacTypes) types).getOverriddenMethods(currElement); - AccessKind ak = AccessKind.PUBLIC; + // It's convenient to use AccessLevel to model effects that nesting has + // on access. While very similar, those are not the same concept. + var mostLimitingSoFar = AccessLevel.PUBLIC; for (TreePath p = path; p != null; p = p.getParentPath()) { Element e = trees.getElement(p); if (e != null && e.getKind() != ElementKind.PACKAGE && e.getKind() != ElementKind.MODULE) { - ak = min(ak, AccessKind.of(e.getModifiers())); + var level = AccessLevel.of(e.getModifiers()); + mostLimitingSoFar = mostLimitingSoFar.compareTo(level) <= 0 + ? mostLimitingSoFar : level; } } - currAccess = ak; - } - - AccessKind getAccessKind() { - return currAccess; + currAccess = mostLimitingSoFar; } long getPos(TreePath p) { @@ -359,11 +334,4 @@ public class Env { } return List.of(); } - - - private <T extends Comparable<T>> T min(T item1, T item2) { - return (item1 == null) ? item2 - : (item2 == null) ? item1 - : item1.compareTo(item2) <= 0 ? item1 : item2; - } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Messages.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Messages.java index 7d38e511d03..2e6bc6f339b 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Messages.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Messages.java @@ -43,7 +43,7 @@ import com.sun.source.doctree.DocTree; import com.sun.source.tree.Tree; import com.sun.tools.javac.api.JavacTrees; import com.sun.tools.javac.util.StringUtils; -import jdk.javadoc.internal.doclint.Env.AccessKind; +import jdk.javadoc.internal.tool.AccessLevel; /** * Message reporting for DocLint. @@ -109,8 +109,8 @@ public class Messages { stats.setEnabled(b); } - boolean isEnabled(Group group, Env.AccessKind ak) { - return options.isEnabled(group, ak); + boolean isEnabled(Group group, AccessLevel al) { + return options.isEnabled(group, al); } void reportStats(PrintWriter out) { @@ -176,7 +176,7 @@ public class Messages { * Handler for (sub)options specific to message handling. */ static class Options { - Map<String, Env.AccessKind> map = new HashMap<>(); + private final Map<String, AccessLevel> map = new HashMap<>(); private final Stats stats; static boolean isValidOptions(String opts) { @@ -195,7 +195,13 @@ public class Messages { int sep = opt.indexOf("/"); String grp = opt.substring(begin, (sep != -1) ? sep : opt.length()); return ((begin == 0 && grp.equals("all")) || Group.accepts(grp)) - && ((sep == -1) || AccessKind.accepts(opt.substring(sep + 1))); + && ((sep == -1) || accepts(opt.substring(sep + 1))); + } + + static boolean accepts(String opt) { + for (var level: AccessLevel.values()) + if (opt.equals(StringUtils.toLowerCase(level.name()))) return true; + return false; } Options(Stats stats) { @@ -203,19 +209,18 @@ public class Messages { } /** Determine if a message group is enabled for a particular access level. */ - boolean isEnabled(Group g, Env.AccessKind access) { + boolean isEnabled(Group g, AccessLevel access) { if (map.isEmpty()) - map.put("all", Env.AccessKind.PROTECTED); + map.put(ALL, AccessLevel.PROTECTED); - Env.AccessKind ak = map.get(g.optName()); - if (ak != null && access.compareTo(ak) >= 0) + AccessLevel al = map.get(g.optName()); + if (al != null && access.compareTo(al) >= 0) return true; - ak = map.get(ALL); - if (ak != null && access.compareTo(ak) >= 0) { - ak = map.get(g.notOptName()); - if (ak == null || access.compareTo(ak) > 0) // note >, not >= - return true; + al = map.get(ALL); + if (al != null && access.compareTo(al) >= 0) { + al = map.get(g.notOptName()); + return al == null || access.compareTo(al) > 0; // note >, not >= } return false; @@ -223,7 +228,7 @@ public class Messages { void setOptions(String opts) { if (opts == null) - setOption(ALL, Env.AccessKind.PRIVATE); + setOption(ALL, AccessLevel.PRIVATE); else { for (String opt: opts.split(",")) setOption(StringUtils.toLowerCase(opt.trim())); @@ -238,16 +243,16 @@ public class Messages { int sep = arg.indexOf("/"); if (sep > 0) { - Env.AccessKind ak = Env.AccessKind.valueOf(StringUtils.toUpperCase(arg.substring(sep + 1))); - setOption(arg.substring(0, sep), ak); + var al = AccessLevel.valueOf(StringUtils.toUpperCase(arg.substring(sep + 1))); + setOption(arg.substring(0, sep), al); } else { setOption(arg, null); } } - private void setOption(String opt, Env.AccessKind ak) { - map.put(opt, (ak != null) ? ak - : opt.startsWith("-") ? Env.AccessKind.PUBLIC : Env.AccessKind.PRIVATE); + private void setOption(String opt, AccessLevel al) { + map.put(opt, (al != null) ? al + : opt.startsWith("-") ? AccessLevel.PUBLIC : AccessLevel.PRIVATE); } private static final String ALL = "all"; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/AccessKind.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/AccessLevel.java similarity index 52% rename from src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/AccessKind.java rename to src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/AccessLevel.java index 2e07a421acb..97481fa2f08 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/AccessKind.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/AccessLevel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,16 +25,40 @@ package jdk.javadoc.internal.tool; +import java.util.Set; +import javax.lang.model.element.Modifier; + /** - * The access value kinds. + * The access levels. + * + * These constants are ordered by their access limiting power. The bigger the + * {@link #ordinal() ordinal} of a constant, the more limiting power that + * constant has. + * + * That has a few useful implications. For example, the levels can be compared + * by {@link #compareTo}. It also means that {@code AccessLevel.values()[0]} and + * {@code AccessLevel.values()[values.length() - 1] and the constants with the + * smallest and the biggest limiting powers respectively. */ -public enum AccessKind { - /** Limits access to public entities */ - PUBLIC, +public enum AccessLevel implements Comparable<AccessLevel> { + + /** Does not limit access */ + PRIVATE, + /** Limits access to entities that are public, protected, or declared with package access */ + PACKAGE, /** Limits access to public and protected entities */ PROTECTED, - /** Limits access to public, protected and package private entities */ - PACKAGE, - /** No limits */ - PRIVATE; + /** Limits access to public entities */ + PUBLIC; + + public static AccessLevel of(Set<Modifier> mods) { + if (mods.contains(Modifier.PUBLIC)) + return AccessLevel.PUBLIC; + else if (mods.contains(Modifier.PROTECTED)) + return AccessLevel.PROTECTED; + else if (mods.contains(Modifier.PRIVATE)) + return AccessLevel.PRIVATE; + else + return AccessLevel.PACKAGE; + } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java index e915fc5f34c..7f4f31844f5 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java @@ -192,7 +192,7 @@ public class ElementsTable { private final ModifierFilter accessFilter; - private final AccessKind expandRequires; + private final AccessLevel expandRequires; final boolean xclasses; @@ -605,8 +605,8 @@ public class ElementsTable { return; } - final boolean expandAll = expandRequires.equals(AccessKind.PRIVATE) - || expandRequires.equals(AccessKind.PACKAGE); + final boolean expandAll = expandRequires.equals(AccessLevel.PRIVATE) + || expandRequires.equals(AccessLevel.PACKAGE); Set<ModuleElement> result = new LinkedHashSet<>(); ListBuffer<ModuleElement> queue = new ListBuffer<>(); @@ -657,13 +657,13 @@ public class ElementsTable { } private Set<PackageElement> computeModulePackages() throws ToolException { - AccessKind accessValue = accessFilter.getAccessValue(ElementKind.PACKAGE); - final boolean documentAllModulePackages = (accessValue == AccessKind.PACKAGE || - accessValue == AccessKind.PRIVATE); + AccessLevel accessValue = accessFilter.getAccessValue(ElementKind.PACKAGE); + final boolean documentAllModulePackages = (accessValue == AccessLevel.PACKAGE || + accessValue == AccessLevel.PRIVATE); accessValue = accessFilter.getAccessValue(ElementKind.MODULE); - final boolean moduleDetailedMode = (accessValue == AccessKind.PACKAGE || - accessValue == AccessKind.PRIVATE); + final boolean moduleDetailedMode = (accessValue == AccessLevel.PACKAGE || + accessValue == AccessLevel.PRIVATE); Set<PackageElement> expandedModulePackages = new LinkedHashSet<>(); for (ModuleElement mdle : specifiedModuleElements) { @@ -1185,12 +1185,8 @@ public class ElementsTable { ElementKind.PACKAGE, ElementKind.MODULE); - // all possible access levels allowed for each element - private final EnumMap<ElementKind, EnumSet<AccessKind>> filterMap = - new EnumMap<>(ElementKind.class); - - // the specified access level for each element - private final EnumMap<ElementKind, AccessKind> accessMap = + // the allowed access level for each element kind + private final EnumMap<ElementKind, AccessLevel> allowedAccess = new EnumMap<>(ElementKind.class); /** @@ -1199,35 +1195,23 @@ public class ElementsTable { * @param options the tool options */ ModifierFilter(ToolOptions options) { - - AccessKind accessValue = null; for (ElementKind kind : ALLOWED_KINDS) { - accessValue = switch (kind) { + var accessValue = switch (kind) { case METHOD -> options.showMembersAccess(); case CLASS -> options.showTypesAccess(); case PACKAGE -> options.showPackagesAccess(); case MODULE -> options.showModuleContents(); default -> throw new AssertionError("unknown element: " + kind); }; - accessMap.put(kind, accessValue); - filterMap.put(kind, getFilterSet(accessValue)); + allowedAccess.put(kind, accessValue); } } - static EnumSet<AccessKind> getFilterSet(AccessKind accessValue) { - return switch (accessValue) { - case PUBLIC -> EnumSet.of(AccessKind.PUBLIC); - case PROTECTED -> EnumSet.of(AccessKind.PUBLIC, AccessKind.PROTECTED); - case PACKAGE -> EnumSet.of(AccessKind.PUBLIC, AccessKind.PROTECTED, AccessKind.PACKAGE); - case PRIVATE -> EnumSet.allOf(AccessKind.class); - }; - } - - public AccessKind getAccessValue(ElementKind kind) { + public AccessLevel getAccessValue(ElementKind kind) { if (!ALLOWED_KINDS.contains(kind)) { throw new IllegalArgumentException("not allowed: " + kind); } - return accessMap.getOrDefault(kind, AccessKind.PROTECTED); + return allowedAccess.getOrDefault(kind, AccessLevel.PROTECTED); } /** @@ -1237,21 +1221,13 @@ public class ElementsTable { * @return whether the modifiers pass this filter */ public boolean checkModifier(Element e) { - Set<Modifier> modifiers = e.getModifiers(); - AccessKind fflag = AccessKind.PACKAGE; - if (modifiers.contains(Modifier.PUBLIC)) { - fflag = AccessKind.PUBLIC; - } else if (modifiers.contains(Modifier.PROTECTED)) { - fflag = AccessKind.PROTECTED; - } else if (modifiers.contains(Modifier.PRIVATE)) { - fflag = AccessKind.PRIVATE; - } - EnumSet<AccessKind> filterSet = filterMap.get(getAllowedKind(e.getKind())); - return filterSet.contains(fflag); + var access = AccessLevel.of(e.getModifiers()); + return allowedAccess.get(toTrackedKind(e.getKind())).compareTo(access) <= 0; } - // convert a requested element kind to an allowed access kind - private ElementKind getAllowedKind(ElementKind kind) { + // convert the requested element kind to a tracked access kind + // (access is tracked for certain kinds only) + private ElementKind toTrackedKind(ElementKind kind) { return switch (kind) { case CLASS, METHOD, MODULE, PACKAGE -> kind; case RECORD, ANNOTATION_TYPE, ENUM, INTERFACE -> ElementKind.CLASS; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOptions.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOptions.java index 07f53f70924..d478e878a5c 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOptions.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOptions.java @@ -85,7 +85,7 @@ public class ToolOptions { /** * Argument for command-line option {@code --expand-requires}. */ - private AccessKind expandRequires; + private AccessLevel expandRequires; /** * Argument for command-line option {@code --ignore-source-errors}. @@ -106,22 +106,22 @@ public class ToolOptions { /** * Argument for command-line option {@code --show-members}. */ - private AccessKind showMembersAccess; + private AccessLevel showMembersAccess; /** * Argument for command-line option {@code --show-types}. */ - private AccessKind showTypesAccess; + private AccessLevel showTypesAccess; /** * Argument for command-line option {@code --show-packages}. */ - private AccessKind showPackagesAccess; + private AccessLevel showPackagesAccess; /** * Argument for command-line option {@code --show-module-contents}. */ - private AccessKind showModuleContents; + private AccessLevel showModuleContents; /** * Argument for command-line option {@code -quiet}. @@ -717,7 +717,7 @@ public class ToolOptions { /** * Argument for command-line option {@code --expand-requires}. */ - AccessKind expandRequires() { + AccessLevel expandRequires() { return expandRequires; } @@ -746,28 +746,28 @@ public class ToolOptions { /** * Argument for command-line option {@code --show-members}. */ - AccessKind showMembersAccess() { + AccessLevel showMembersAccess() { return showMembersAccess; } /** * Argument for command-line option {@code --show-types}. */ - AccessKind showTypesAccess() { + AccessLevel showTypesAccess() { return showTypesAccess; } /** * Argument for command-line option {@code --show-packages}. */ - AccessKind showPackagesAccess() { + AccessLevel showPackagesAccess() { return showPackagesAccess; } /** * Argument for command-line option {@code --show-module-contents}. */ - AccessKind showModuleContents() { + AccessLevel showModuleContents() { return showModuleContents; } @@ -885,40 +885,25 @@ public class ToolOptions { private void setExpandRequires(String arg) throws OptionException { switch (arg) { - case "transitive": - expandRequires = AccessKind.PUBLIC; - break; - case "all": - expandRequires = AccessKind.PRIVATE; - break; - default: - throw illegalOptionValue(arg); + case "transitive" -> expandRequires = AccessLevel.PUBLIC; + case "all" -> expandRequires = AccessLevel.PRIVATE; + default -> throw illegalOptionValue(arg); } } private void setShowModuleContents(String arg) throws OptionException { switch (arg) { - case "api": - showModuleContents = AccessKind.PUBLIC; - break; - case "all": - showModuleContents = AccessKind.PRIVATE; - break; - default: - throw illegalOptionValue(arg); + case "api" -> showModuleContents = AccessLevel.PUBLIC; + case "all" -> showModuleContents = AccessLevel.PRIVATE; + default -> throw illegalOptionValue(arg); } } private void setShowPackageAccess(String arg) throws OptionException { switch (arg) { - case "exported": - showPackagesAccess = AccessKind.PUBLIC; - break; - case "all": - showPackagesAccess = AccessKind.PRIVATE; - break; - default: - throw illegalOptionValue(arg); + case "exported" -> showPackagesAccess = AccessLevel.PUBLIC; + case "all" -> showPackagesAccess = AccessLevel.PRIVATE; + default -> throw illegalOptionValue(arg); } } @@ -948,53 +933,37 @@ public class ToolOptions { * -private, so on, in addition to the new ones such as * --show-types:public and so on. */ - private AccessKind getAccessValue(String arg) throws OptionException { + private AccessLevel getAccessValue(String arg) throws OptionException { int colon = arg.indexOf(':'); - String value = (colon > 0) - ? arg.substring(colon + 1) - : arg; - switch (value) { - case "public": - return AccessKind.PUBLIC; - case "protected": - return AccessKind.PROTECTED; - case "package": - return AccessKind.PACKAGE; - case "private": - return AccessKind.PRIVATE; - default: - throw illegalOptionValue(value); - } + String value = (colon > 0) ? arg.substring(colon + 1) : arg; + return switch (value) { + case "public" -> AccessLevel.PUBLIC; + case "protected" -> AccessLevel.PROTECTED; + case "package" -> AccessLevel.PACKAGE; + case "private" -> AccessLevel.PRIVATE; + default -> throw illegalOptionValue(value); + }; } /* * Sets all access members to PROTECTED; this is the default. */ private void setAccessDefault() { - setAccess(AccessKind.PROTECTED); + setAccess(AccessLevel.PROTECTED); } /* - * This sets access to all the allowed kinds in the + * Sets access level to all the allowed kinds in the * access members. */ - private void setAccess(AccessKind accessValue) { + private void setAccess(AccessLevel accessValue) { for (ElementKind kind : ElementsTable.ModifierFilter.ALLOWED_KINDS) { switch (kind) { - case METHOD: - showMembersAccess = accessValue; - break; - case CLASS: - showTypesAccess = accessValue; - break; - case PACKAGE: - showPackagesAccess = accessValue; - break; - case MODULE: - showModuleContents = accessValue; - break; - default: - throw new AssertionError("unknown element kind:" + kind); + case METHOD -> showMembersAccess = accessValue; + case CLASS -> showTypesAccess = accessValue; + case PACKAGE -> showPackagesAccess = accessValue; + case MODULE -> showModuleContents = accessValue; + default -> throw new AssertionError("unknown element kind:" + kind); } } }