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