1 /* 2 * Copyright (c) 2012, 2019, 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.doclint; 27 28 29 import java.util.Arrays; 30 import java.util.HashSet; 31 import java.util.LinkedHashSet; 32 import java.util.List; 33 import java.util.Set; 34 import java.util.regex.Pattern; 35 36 import javax.lang.model.element.Element; 37 import javax.lang.model.element.ElementKind; 38 import javax.lang.model.element.ExecutableElement; 39 import javax.lang.model.element.Modifier; 40 import javax.lang.model.type.TypeMirror; 41 import javax.lang.model.util.Elements; 42 import javax.lang.model.util.Types; 43 import javax.tools.Diagnostic.Kind; 44 45 import com.sun.source.doctree.DocCommentTree; 46 import com.sun.source.tree.CompilationUnitTree; 47 import com.sun.source.util.DocTrees; 48 import com.sun.source.util.JavacTask; 49 import com.sun.source.util.SourcePositions; 50 import com.sun.source.util.TreePath; 51 import com.sun.tools.javac.model.JavacTypes; 52 import com.sun.tools.javac.tree.JCTree; 53 import com.sun.tools.javac.util.MatchingUtils; 54 import com.sun.tools.javac.util.StringUtils; 55 56 /** 57 * Utility container for current execution environment, 58 * providing the current declaration and its doc comment. 59 * 60 * <p><b>This is NOT part of any supported API. 61 * If you write code that depends on this, you do so at your own 62 * risk. This code and its internal interfaces are subject to change 63 * or deletion without notice.</b></p> 64 */ 65 public class Env { 66 /** 67 * Access kinds for declarations. 68 */ 69 public enum AccessKind { 70 PRIVATE, 71 PACKAGE, 72 PROTECTED, 73 PUBLIC; 74 accepts(String opt)75 static boolean accepts(String opt) { 76 for (AccessKind g: values()) 77 if (opt.equals(StringUtils.toLowerCase(g.name()))) return true; 78 return false; 79 } 80 of(Set<Modifier> mods)81 static AccessKind of(Set<Modifier> mods) { 82 if (mods.contains(Modifier.PUBLIC)) 83 return AccessKind.PUBLIC; 84 else if (mods.contains(Modifier.PROTECTED)) 85 return AccessKind.PROTECTED; 86 else if (mods.contains(Modifier.PRIVATE)) 87 return AccessKind.PRIVATE; 88 else 89 return AccessKind.PACKAGE; 90 } 91 } 92 93 /** Message handler. */ 94 final Messages messages; 95 96 Set<String> customTags; 97 98 Set<Pattern> includePackages; 99 Set<Pattern> excludePackages; 100 101 HtmlVersion htmlVersion = HtmlVersion.HTML4; 102 103 // Utility classes 104 DocTrees trees; 105 Elements elements; 106 Types types; 107 108 // Types used when analysing doc comments. 109 TypeMirror java_lang_Error; 110 TypeMirror java_lang_RuntimeException; 111 TypeMirror java_lang_Throwable; 112 TypeMirror java_lang_Void; 113 114 /** The path for the declaration containing the comment currently being analyzed. */ 115 TreePath currPath; 116 /** The element for the declaration containing the comment currently being analyzed. */ 117 Element currElement; 118 /** The comment current being analyzed. */ 119 DocCommentTree currDocComment; 120 /** 121 * The access kind of the declaration containing the comment currently being analyzed. 122 * This is the minimum (most restrictive) access kind of the declaration itself 123 * and that of its containers. For example, a public method in a private class is 124 * noted as private. 125 */ 126 AccessKind currAccess; 127 /** The set of methods, if any, that the current declaration overrides. */ 128 Set<? extends ExecutableElement> currOverriddenMethods; 129 Env()130 Env() { 131 messages = new Messages(this); 132 } 133 init(JavacTask task)134 void init(JavacTask task) { 135 init(DocTrees.instance(task), task.getElements(), task.getTypes()); 136 } 137 init(DocTrees trees, Elements elements, Types types)138 void init(DocTrees trees, Elements elements, Types types) { 139 this.trees = trees; 140 this.elements = elements; 141 this.types = types; 142 } 143 initTypes()144 void initTypes() { 145 if (java_lang_Error != null) 146 return ; 147 148 java_lang_Error = elements.getTypeElement("java.lang.Error").asType(); 149 java_lang_RuntimeException = elements.getTypeElement("java.lang.RuntimeException").asType(); 150 java_lang_Throwable = elements.getTypeElement("java.lang.Throwable").asType(); 151 java_lang_Void = elements.getTypeElement("java.lang.Void").asType(); 152 } 153 setCustomTags(String cTags)154 void setCustomTags(String cTags) { 155 customTags = new LinkedHashSet<>(); 156 for (String s : cTags.split(DocLint.SEPARATOR)) { 157 if (!s.isEmpty()) 158 customTags.add(s); 159 } 160 } 161 setCheckPackages(String packages)162 void setCheckPackages(String packages) { 163 includePackages = new HashSet<>(); 164 excludePackages = new HashSet<>(); 165 for (String pack : packages.split(DocLint.SEPARATOR)) { 166 boolean excluded = false; 167 if (pack.startsWith("-")) { 168 pack = pack.substring(1); 169 excluded = true; 170 } 171 if (pack.isEmpty()) 172 continue; 173 Pattern pattern = MatchingUtils.validImportStringToPattern(pack); 174 if (excluded) { 175 excludePackages.add(pattern); 176 } else { 177 includePackages.add(pattern); 178 } 179 } 180 } 181 validatePackages(String packages)182 static boolean validatePackages(String packages) { 183 for (String pack : packages.split(DocLint.SEPARATOR)) { 184 if (pack.startsWith("-")) { 185 pack = pack.substring(1); 186 } 187 if (!pack.isEmpty() && !MatchingUtils.isValidImportString(pack)) 188 return false; 189 } 190 return true; 191 } 192 setHtmlVersion(HtmlVersion version)193 void setHtmlVersion(HtmlVersion version) { 194 htmlVersion = version; 195 } 196 197 /** Set the current declaration and its doc comment. */ setCurrent(TreePath path, DocCommentTree comment)198 void setCurrent(TreePath path, DocCommentTree comment) { 199 currPath = path; 200 currDocComment = comment; 201 currElement = trees.getElement(currPath); 202 currOverriddenMethods = ((JavacTypes) types).getOverriddenMethods(currElement); 203 204 AccessKind ak = AccessKind.PUBLIC; 205 for (TreePath p = path; p != null; p = p.getParentPath()) { 206 Element e = trees.getElement(p); 207 if (e != null && e.getKind() != ElementKind.PACKAGE && e.getKind() != ElementKind.MODULE) { 208 ak = min(ak, AccessKind.of(e.getModifiers())); 209 } 210 } 211 currAccess = ak; 212 } 213 getAccessKind()214 AccessKind getAccessKind() { 215 return currAccess; 216 } 217 getPos(TreePath p)218 long getPos(TreePath p) { 219 return ((JCTree) p.getLeaf()).pos; 220 } 221 getStartPos(TreePath p)222 long getStartPos(TreePath p) { 223 SourcePositions sp = trees.getSourcePositions(); 224 return sp.getStartPosition(p.getCompilationUnit(), p.getLeaf()); 225 } 226 shouldCheck(CompilationUnitTree unit)227 boolean shouldCheck(CompilationUnitTree unit) { 228 if (includePackages == null) 229 return true; 230 231 String packageName = unit.getPackageName() != null 232 ? unit.getPackageName().toString() 233 : ""; 234 235 if (!includePackages.isEmpty()) { 236 boolean included = false; 237 for (Pattern pack : includePackages) { 238 if (pack.matcher(packageName).matches()) { 239 included = true; 240 break; 241 } 242 } 243 if (!included) 244 return false; 245 } 246 247 for (Pattern pack : excludePackages) { 248 if (pack.matcher(packageName).matches()) { 249 return false; 250 } 251 } 252 253 return true; 254 } 255 min(T item1, T item2)256 private <T extends Comparable<T>> T min(T item1, T item2) { 257 return (item1 == null) ? item2 258 : (item2 == null) ? item1 259 : item1.compareTo(item2) <= 0 ? item1 : item2; 260 } 261 } 262