1 /* 2 * Copyright (c) 2003, 2013, 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.javadoc; 27 28 import com.sun.source.util.TreePath; 29 import com.sun.tools.javac.code.Flags; 30 import com.sun.tools.javac.code.Kinds; 31 import com.sun.tools.javac.code.Symbol.*; 32 import com.sun.tools.javac.comp.MemberEnter; 33 import com.sun.tools.javac.tree.JCTree; 34 import com.sun.tools.javac.tree.JCTree.*; 35 import com.sun.tools.javac.util.Context; 36 37 import static com.sun.tools.javac.code.Flags.*; 38 39 /** 40 * Javadoc's own memberEnter phase does a few things above and beyond that 41 * done by javac. 42 * 43 * <p><b>This is NOT part of any supported API. 44 * If you write code that depends on this, you do so at your own risk. 45 * This code and its internal interfaces are subject to change or 46 * deletion without notice.</b> 47 * 48 * @author Neal Gafter 49 */ 50 public class JavadocMemberEnter extends MemberEnter { instance0(Context context)51 public static JavadocMemberEnter instance0(Context context) { 52 MemberEnter instance = context.get(memberEnterKey); 53 if (instance == null) 54 instance = new JavadocMemberEnter(context); 55 return (JavadocMemberEnter)instance; 56 } 57 preRegister(Context context)58 public static void preRegister(Context context) { 59 context.put(memberEnterKey, new Context.Factory<MemberEnter>() { 60 public MemberEnter make(Context c) { 61 return new JavadocMemberEnter(c); 62 } 63 }); 64 } 65 66 final DocEnv docenv; 67 JavadocMemberEnter(Context context)68 protected JavadocMemberEnter(Context context) { 69 super(context); 70 docenv = DocEnv.instance(context); 71 } 72 73 @Override visitMethodDef(JCMethodDecl tree)74 public void visitMethodDef(JCMethodDecl tree) { 75 super.visitMethodDef(tree); 76 MethodSymbol meth = tree.sym; 77 if (meth == null || meth.kind != Kinds.MTH) return; 78 TreePath treePath = docenv.getTreePath(env.toplevel, env.enclClass, tree); 79 if (meth.isConstructor()) 80 docenv.makeConstructorDoc(meth, treePath); 81 else if (isAnnotationTypeElement(meth)) 82 docenv.makeAnnotationTypeElementDoc(meth, treePath); 83 else 84 docenv.makeMethodDoc(meth, treePath); 85 86 // release resources 87 tree.body = null; 88 } 89 90 @Override visitVarDef(JCVariableDecl tree)91 public void visitVarDef(JCVariableDecl tree) { 92 if (tree.init != null) { 93 boolean isFinal = (tree.mods.flags & FINAL) != 0 94 || (env.enclClass.mods.flags & INTERFACE) != 0; 95 if (!isFinal || containsNonConstantExpression(tree.init)) { 96 // Avoid unnecessary analysis and release resources. 97 // In particular, remove non-constant expressions 98 // which may trigger Attr.attribClass, since 99 // method bodies are also removed, in visitMethodDef. 100 tree.init = null; 101 } 102 } 103 super.visitVarDef(tree); 104 if (tree.sym != null && 105 tree.sym.kind == Kinds.VAR && 106 !isParameter(tree.sym)) { 107 docenv.makeFieldDoc(tree.sym, docenv.getTreePath(env.toplevel, env.enclClass, tree)); 108 } 109 } 110 isAnnotationTypeElement(MethodSymbol meth)111 private static boolean isAnnotationTypeElement(MethodSymbol meth) { 112 return ClassDocImpl.isAnnotationType(meth.enclClass()); 113 } 114 isParameter(VarSymbol var)115 private static boolean isParameter(VarSymbol var) { 116 return (var.flags() & Flags.PARAMETER) != 0; 117 } 118 119 /** 120 * Simple analysis of an expression tree to see if it contains tree nodes 121 * for any non-constant expression. This does not include checking references 122 * to other fields which may or may not be constant. 123 */ containsNonConstantExpression(JCExpression tree)124 private static boolean containsNonConstantExpression(JCExpression tree) { 125 return new MaybeConstantExpressionScanner().containsNonConstantExpression(tree); 126 } 127 128 /** 129 * See JLS 15.18, Constant Expression 130 */ 131 private static class MaybeConstantExpressionScanner extends JCTree.Visitor { 132 boolean maybeConstantExpr = true; 133 containsNonConstantExpression(JCExpression tree)134 public boolean containsNonConstantExpression(JCExpression tree) { 135 scan(tree); 136 return !maybeConstantExpr; 137 } 138 scan(JCTree tree)139 public void scan(JCTree tree) { 140 // short circuit scan when end result is definitely false 141 if (maybeConstantExpr && tree != null) 142 tree.accept(this); 143 } 144 145 @Override 146 /** default for any non-overridden visit method. */ visitTree(JCTree tree)147 public void visitTree(JCTree tree) { 148 maybeConstantExpr = false; 149 } 150 151 @Override visitBinary(JCBinary tree)152 public void visitBinary(JCBinary tree) { 153 switch (tree.getTag()) { 154 case MUL: case DIV: case MOD: 155 case PLUS: case MINUS: 156 case SL: case SR: case USR: 157 case LT: case LE: case GT: case GE: 158 case EQ: case NE: 159 case BITAND: case BITXOR: case BITOR: 160 case AND: case OR: 161 break; 162 default: 163 maybeConstantExpr = false; 164 } 165 } 166 167 @Override visitConditional(JCConditional tree)168 public void visitConditional(JCConditional tree) { 169 scan(tree.cond); 170 scan(tree.truepart); 171 scan(tree.falsepart); 172 } 173 174 @Override visitIdent(JCIdent tree)175 public void visitIdent(JCIdent tree) { } 176 177 @Override visitLiteral(JCLiteral tree)178 public void visitLiteral(JCLiteral tree) { } 179 180 @Override visitParens(JCParens tree)181 public void visitParens(JCParens tree) { 182 scan(tree.expr); 183 } 184 185 @Override visitSelect(JCTree.JCFieldAccess tree)186 public void visitSelect(JCTree.JCFieldAccess tree) { 187 scan(tree.selected); 188 } 189 190 @Override visitTypeCast(JCTypeCast tree)191 public void visitTypeCast(JCTypeCast tree) { 192 scan(tree.clazz); 193 scan(tree.expr); 194 } 195 196 @Override visitTypeIdent(JCPrimitiveTypeTree tree)197 public void visitTypeIdent(JCPrimitiveTypeTree tree) { } 198 199 @Override visitUnary(JCUnary tree)200 public void visitUnary(JCUnary tree) { 201 switch (tree.getTag()) { 202 case POS: case NEG: case COMPL: case NOT: 203 break; 204 default: 205 maybeConstantExpr = false; 206 } 207 } 208 } 209 } 210