1 /* 2 * Copyright (c) 2003, 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 26 package jdk.javadoc.internal.tool; 27 28 import com.sun.source.util.TreePath; 29 import com.sun.tools.javac.code.Flags; 30 import com.sun.tools.javac.code.Symbol.*; 31 import com.sun.tools.javac.comp.MemberEnter; 32 import com.sun.tools.javac.tree.JCTree; 33 import com.sun.tools.javac.tree.JCTree.*; 34 import com.sun.tools.javac.util.Context; 35 36 import static com.sun.tools.javac.code.Flags.*; 37 import static com.sun.tools.javac.code.Kinds.Kind.*; 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 { 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 58 public static void preRegister(Context context) { 59 context.put(memberEnterKey, (Context.Factory<MemberEnter>)JavadocMemberEnter::new); 60 } 61 62 final ToolEnvironment toolEnv; 63 64 protected JavadocMemberEnter(Context context) { 65 super(context); 66 toolEnv = ToolEnvironment.instance(context); 67 } 68 69 @Override 70 public void visitMethodDef(JCMethodDecl tree) { 71 super.visitMethodDef(tree); 72 MethodSymbol meth = tree.sym; 73 if (meth == null || meth.kind != MTH) return; 74 TreePath treePath = toolEnv.getTreePath(env.toplevel, env.enclClass, tree); 75 // do not add those methods that may be mandated by the spec, 76 // or those that are synthesized, thus if it does not exist in 77 // tree best to let other logic determine the TreePath. 78 if (env.enclClass.defs.contains(tree)) { 79 toolEnv.setElementToTreePath(meth, treePath); 80 } 81 // release resources 82 tree.body = null; 83 } 84 85 @Override 86 public void visitVarDef(JCVariableDecl tree) { 87 if (tree.init != null) { 88 boolean isFinal = (tree.mods.flags & FINAL) != 0 89 || (env.enclClass.mods.flags & INTERFACE) != 0; 90 if (!isFinal || containsNonConstantExpression(tree.init)) { 91 // Avoid unnecessary analysis and release resources. 92 // In particular, remove non-constant expressions 93 // which may trigger Attr.attribClass, since 94 // method bodies are also removed, in visitMethodDef. 95 tree.init = null; 96 } 97 } 98 super.visitVarDef(tree); 99 if (tree.sym != null && tree.sym.kind == VAR && !isParameter(tree.sym)) { 100 toolEnv.setElementToTreePath(tree.sym, toolEnv.getTreePath(env.toplevel, env.enclClass, tree)); 101 } 102 } 103 104 private static boolean isParameter(VarSymbol var) { 105 return (var.flags() & Flags.PARAMETER) != 0; 106 } 107 108 /** 109 * Simple analysis of an expression tree to see if it contains tree nodes 110 * for any non-constant expression. This does not include checking references 111 * to other fields which may or may not be constant. 112 */ 113 private static boolean containsNonConstantExpression(JCExpression tree) { 114 return new MaybeConstantExpressionScanner().containsNonConstantExpression(tree); 115 } 116 117 /** 118 * See JLS 15.18, Constant Expression 119 */ 120 private static class MaybeConstantExpressionScanner extends JCTree.Visitor { 121 boolean maybeConstantExpr = true; 122 123 public boolean containsNonConstantExpression(JCExpression tree) { 124 scan(tree); 125 return !maybeConstantExpr; 126 } 127 128 public void scan(JCTree tree) { 129 // short circuit scan when end result is definitely false 130 if (maybeConstantExpr && tree != null) 131 tree.accept(this); 132 } 133 134 @Override 135 /** default for any non-overridden visit method. */ 136 public void visitTree(JCTree tree) { 137 maybeConstantExpr = false; 138 } 139 140 @Override 141 public void visitBinary(JCBinary tree) { 142 switch (tree.getTag()) { 143 case MUL: case DIV: case MOD: 144 case PLUS: case MINUS: 145 case SL: case SR: case USR: 146 case LT: case LE: case GT: case GE: 147 case EQ: case NE: 148 case BITAND: case BITXOR: case BITOR: 149 case AND: case OR: 150 break; 151 default: 152 maybeConstantExpr = false; 153 } 154 } 155 156 @Override 157 public void visitConditional(JCConditional tree) { 158 scan(tree.cond); 159 scan(tree.truepart); 160 scan(tree.falsepart); 161 } 162 163 @Override 164 public void visitIdent(JCIdent tree) { } 165 166 @Override 167 public void visitLiteral(JCLiteral tree) { } 168 169 @Override 170 public void visitParens(JCParens tree) { 171 scan(tree.expr); 172 } 173 174 @Override 175 public void visitSelect(JCTree.JCFieldAccess tree) { 176 scan(tree.selected); 177 } 178 179 @Override 180 public void visitTypeCast(JCTypeCast tree) { 181 scan(tree.clazz); 182 scan(tree.expr); 183 } 184 185 @Override 186 public void visitTypeIdent(JCPrimitiveTypeTree tree) { } 187 188 @Override 189 public void visitUnary(JCUnary tree) { 190 switch (tree.getTag()) { 191 case POS: case NEG: case COMPL: case NOT: 192 break; 193 default: 194 maybeConstantExpr = false; 195 } 196 } 197 } 198 }