1 19 20 package org.netbeans.modules.java.source.script; 21 22 import org.netbeans.modules.java.source.engine.EngineEnvironment; 23 import org.netbeans.modules.java.source.engine.ASTModel; 24 import org.netbeans.modules.java.source.engine.RootTree; 25 import com.sun.source.tree.CompilationUnitTree; 26 import com.sun.source.tree.ExpressionStatementTree; 27 import com.sun.source.tree.Tree; 28 import javax.lang.model.element.Element; 29 import javax.lang.model.element.PackageElement; 30 import org.netbeans.api.java.source.transform.ImmutableTreeTranslator; 31 import org.netbeans.api.java.source.transform.Transformer; 32 import org.netbeans.modules.java.source.engine.EngineEnvironment; 33 import org.netbeans.modules.java.source.engine.RecursiveRuleException; 34 import org.netbeans.modules.java.source.engine.RulesParseException; 35 import org.netbeans.api.java.source.query.QueryEnvironment; 36 import org.netbeans.api.java.source.query.Query; 37 38 import com.sun.tools.javac.code.Symtab; 39 import com.sun.tools.javac.comp.Attr; 40 41 import com.sun.tools.javac.code.*; 42 import com.sun.tools.javac.jvm.ClassReader; 43 import com.sun.tools.javac.tree.*; 44 import com.sun.tools.javac.tree.JCTree.*; 45 import com.sun.tools.javac.parser.*; 46 import com.sun.tools.javac.util.*; 47 import org.netbeans.api.java.source.ElementUtilities; 48 import org.netbeans.modules.java.source.engine.RootTree; 49 50 import static com.sun.tools.javac.code.Flags.*; 51 import static com.sun.tools.javac.code.TypeTags.*; 52 53 abstract public class GeneratedMatcher extends Transformer<Void ,Object > { 54 protected final static int MAX_DEPTH = 300; 55 protected Tree[] meta = new Tree[20]; 56 protected Tree[] parentChain = new Tree[MAX_DEPTH]; 57 protected int depth = 0; 58 protected int currentLine = -1; 59 protected String script = ""; 60 private ElementUtilities elements; 61 private JCCompilationUnit currentTopLevel; 62 abstract protected JCTree rewrite(JCTree t); 63 64 public final JCTree rewrite0(JCTree t) { 65 if (++depth >= MAX_DEPTH) 66 throw new RecursiveRuleException(script, currentLine); 67 parentChain[depth] = t; 68 t = rewrite(t); 69 depth--; 70 return t; 71 } 72 73 protected String comment; 74 public ImmutableTreeTranslator rewriter; 75 public Tree rewriteAll(Tree t) { 76 return rewriter.translate(t); 77 } 78 public Tree parentOf(Tree t) { 79 for(int p = depth; --p>0; ) 80 if(parentChain[p]==t) return parentChain[p-1]; 81 return null; 82 } 83 public JCStatement containingStatement() { 84 for(int p = depth; --p>=0; ) 85 if(parentChain[p] instanceof JCStatement) 86 return (JCStatement)parentChain[p]; 87 return null; 88 } 89 public void addComment(String s) { 90 attach(containingStatement(),s); 91 } 92 public Tree parent() { 93 return depth>1 ? parentChain[depth-2] : null; 94 } 95 @Override 96 public void release() { 97 super.release(); 98 rewriter.release(); 99 ee = null; 100 keywords = null; 101 classes = null; 102 elements = null; 103 names = null; 104 symtab = null; 105 jcmake = null; 106 jctypes = null; 107 nullName = null; 108 trueName = null; 109 falseName = null; 110 currentTopLevel = null; 111 } 112 @Override 113 public void attach(QueryEnvironment env) { 114 super.attach(env); 115 ee = (EngineEnvironment)env; 116 keywords = ee.getKeywords(); 117 classes = ee.getClassReader(); 118 names = ee.getNameTable(); 119 symtab = ee.getSymbolTable(); 120 elements = ee.getElementUtilities(); 121 jcmake = com.sun.tools.javac.tree.TreeMaker.instance(ee.getContext()); 122 jctypes = com.sun.tools.javac.code.Types.instance(ee.getContext()); 123 nullName = names.fromString(Token.NULL.name); 124 trueName = names.fromString(Token.TRUE.name); 125 falseName = names.fromString(Token.FALSE.name); 126 try { 127 initializeKeywords(); 128 } catch (ClassNotFoundException e) { 129 throw new RulesParseException("cannot find class: " + e.getMessage()); 130 } 131 rewriter = new ImmutableTreeTranslator() { 132 @Override 133 public Tree visitCompilationUnit(CompilationUnitTree node, Object p) { 134 currentTopLevel = (JCCompilationUnit)node; 135 Tree result = super.visitCompilationUnit(node, p); 136 currentTopLevel = null; 137 return result; 138 } 139 @Override 140 public Tree translate(Tree tree) { 141 if(tree==null) return null; 142 parentChain[depth++] = tree; 143 Tree newtree = super.translate(tree); 144 Tree ret = newtree!=null && 145 (newtree instanceof ExpressionStatementTree || 146 newtree instanceof RootTree) ? 147 newtree : rewrite((JCTree)newtree); 148 depth--; 149 if(ret!=newtree) { 150 155 addResult(super.currentSym, ret, comment); 156 changes.rewrite(tree, ret); 157 if (ret != null) 158 model.setPos(ret, Query.NOPOS); } 160 return ret; 161 } 162 @Override 163 public Tree visitExpressionStatement(ExpressionStatementTree node, Object p) { 164 JCExpressionStatement tree = (JCExpressionStatement)node; 165 tree = (JCExpressionStatement)rewriteChildren(node); 166 Tree result = tree; 167 if(tree==null||tree.expr==null) 168 result=null; 169 else { 170 int tag = tree.expr.tag; 171 if(tag==JCTree.CONDEXPR) { 172 JCConditional s = (JCConditional) tree.expr; 173 result = (JCTree)If(s.cond,jcmake.Exec(s.truepart),jcmake.Exec(s.falsepart)); 174 changeResult(tree.expr,result); 175 } 176 else if(tag<JCTree.APPLY) 177 result = tree.expr; 178 if (result != tree) 179 changes.rewrite(tree, result); 180 } 181 return result; 182 } 183 @Override 184 public <T extends Tree> T translateClassRef(T tree) { 185 tree = (T)translate(tree); 186 187 boolean inImport = currentSym instanceof Symbol.PackageSymbol; 189 190 T result = replaceclass(tree, inImport); 191 if (result != tree) { 192 if (!tree.toString().equals(result.toString())) { 193 Element sym = super.currentSym; 194 if (sym instanceof PackageElement) sym = model.getElement(currentTopLevel.getTypeDecls().get(0)); addResult(sym, result, comment); 197 changes.rewrite(tree, result); 198 } 199 } 200 return result; 201 } 202 }; 203 rewriter.attach(env); 204 } 205 public Symbol getCurrentSymbol() { 206 return (Symbol)rewriter.currentSym; 207 } 208 protected ImmutableTreeTranslator getTranslator() { 209 return rewriter; 210 } 211 public <T extends Tree> T replaceclass(T tree, boolean explicitRef) { 212 JCTree t = (JCTree)tree; 213 if(t!=null) { 214 jcmake.pos = Query.NOPOS; 215 Symbol s = TreeInfo.symbol(t); 216 if(s!=null) { 217 Symbol s2 = replacesymbol(s); 218 if(s2 != s) { 219 if (explicitRef) 220 t = explicitQualIdent(s2); 221 else if (t.tag == JCTree.IDENT) 222 t = jcmake.Ident(s2); 223 else { 224 assert t.tag == JCTree.SELECT; 225 t = jcmake.Select(((JCFieldAccess)t).selected, s2.name); 226 } 227 ASTModel model = ee.getModel(); 228 model.setPos(t, model.getPos(tree)); 229 } 230 } 231 } 232 return (T)t; 233 } 234 235 private JCExpression explicitQualIdent(Symbol sym) { 236 return (sym.name == names.empty || sym.owner == null || 237 sym.owner == symtab.unnamedPackage || sym.owner == symtab.rootPackage || 238 sym.owner.kind == Kinds.MTH || sym.owner.kind == Kinds.VAR) 239 ? jcmake.Ident(sym) 240 : jcmake.Select(explicitQualIdent(sym.owner), sym); 241 } 242 243 public Type replacetype(Type t) { return replacesymbol(t.tsym).type; } 244 public Symbol replacesymbol(Symbol s) { return s; } 245 public boolean isSubType(Type THIS, Type that) { 246 Type rTHIS = replacetype(THIS); 247 Type rthat = replacetype(that); 248 if (THIS == that || rTHIS==rthat) return true; 249 if (that.tag >= firstPartialTag) return jctypes.isSuperType(THIS, that); 250 if (THIS.tsym == that.tsym) 251 return 252 (!that.isParameterized() || 253 jctypes.isSameTypes(THIS.getParameterTypes(), that.getParameterTypes())) && 254 isSubType(THIS.getEnclosingType(),that.getEnclosingType()); 255 if ((that.tsym.flags() & INTERFACE) != 0) 256 for (List<Type> is = jctypes.interfaces(THIS); 257 is.nonEmpty(); 258 is = is.tail) 259 if (isSubType(is.head,that)) return true; 260 Type st = jctypes.supertype(THIS); 261 if(st==null) return false; 262 if (st.tag == CLASS && isSubType(st,that)) 263 return true; 264 return st.isErroneous(); 265 } 266 267 protected Object opGT(Object a, Object b) { 268 return Boolean.valueOf(compare(a,b)>0); 269 } 270 protected Object opGE(Object a, Object b) { 271 return Boolean.valueOf(compare(a,b)>=0); 272 } 273 protected Object opLT(Object a, Object b) { 274 return Boolean.valueOf(compare(b,a)>0); 275 } 276 protected Object opLE(Object a, Object b) { 277 return Boolean.valueOf(compare(b,a)>=0); 278 } 279 protected Object opEQ(Object a, Object b) { 280 return Boolean.valueOf(compare(a,b)==0); 281 } 282 protected Object opNE(Object a, Object b) { 283 return Boolean.valueOf(compare(a,b)!=0); 284 } 285 protected Object findClass(String jar, String clazz) { 286 if("org.netbeans.api.java.source.query.Query".equals(clazz) || 287 "org.netbeans.api.java.source.transform.Transformer".equals(clazz) || 288 "org.netbeans.modules.java.source.script.GeneratedMatcher".equals(clazz)) return this; 289 if(!"".equals(jar)) System.err.println("Unimplimented: "+jar); 290 try { 291 return Class.forName(clazz).newInstance(); 292 } catch(Throwable t) { 293 error(t); 294 return null; 295 } 296 } 297 298 protected JCExpression resolve(JCFieldAccess tree) { 299 Symbol sym = TreeInfo.symbol(tree.selected); 300 if (sym instanceof Symbol.ClassSymbol) { 301 Scope.Entry entry = ((Symbol.ClassSymbol)sym).members().lookup(tree.name); 302 if (entry.sym != null) 303 return doResolve(tree, entry.sym); 304 } 305 Name n = TreeInfo.fullName(tree); 306 sym = resolveIdent(n); 307 if (sym != symtab.errSymbol) 308 return doResolve(tree, sym); 309 return tree; 310 } 311 312 private JCExpression doResolve(JCFieldAccess tree, Symbol sym) { 313 tree.sym = sym; 314 tree.type = sym.asType(); 315 if (sym instanceof Symbol.ClassSymbol) 316 return jcmake.Ident(sym); 318 return tree; 319 } 320 321 protected Symbol.ClassSymbol resolveClass(Name name) throws ClassNotFoundException { 322 Symbol sym = resolveIdent(name); 323 if (sym instanceof Symbol.ClassSymbol) 324 return (Symbol.ClassSymbol)sym; 325 throw new ClassNotFoundException (name.toString()); 326 } 327 328 protected JCTree deblock(JCTree t) { 329 t = (JCTree)Transformer.deblock(t); 330 return t instanceof JCExpressionStatement ? ((JCExpressionStatement)t).expr : t; 331 } 332 333 protected static final <T extends JCTree> List<T> firstN(List<T> t, int n) { 334 return n<=0 || t==null || t.isEmpty() ? List.<T>nil() 335 : firstN(t.tail,n-1).prepend(t.head); 336 } 337 338 protected boolean idMatches(JCFieldAccess t, Name fqn) { 339 if (t.toString().endsWith(".INFORMATIONAL")) 340 System.out.println(); 341 if (t.sym != null && elements.getFullName(t.sym) == fqn) 342 return true; 343 return TreeInfo.fullName(t) == fqn; 344 } 345 346 349 protected Symbol.TypeSymbol resolveIdent(Name name) { 350 Symtab syms = ee.getSymbolTable(); 351 Attr attr = Attr.instance(ee.getContext()); 352 if (name == null || name == names.empty) 353 return syms.errSymbol; 354 JCCompilationUnit toplevel = 355 jcmake.TopLevel(List.<JCTree.JCAnnotation>nil(), null, List.<JCTree>nil()); 356 toplevel.packge = syms.unnamedPackage; 357 classes.complete(toplevel.packge); 358 Scanner.Factory scannerFactory = Scanner.Factory.instance(ee.getContext()); 359 Scanner scanner = scannerFactory.newScanner((name.toString()+"\u0000").toCharArray(), 360 name.length()); 361 Parser.Factory parserFactory = Parser.Factory.instance(ee.getContext()); 362 Parser parser = parserFactory.newParser(scanner, false, false); 363 JCTree tree = parser.qualident(); 364 if (tree != null && (tree instanceof JCFieldAccess || tree instanceof JCIdent)) { 365 Symbol sym = attr.attribIdent(tree, toplevel); 366 return sym instanceof Symbol.TypeSymbol ? (Symbol.TypeSymbol)sym : syms.errSymbol; 367 } 368 return syms.errSymbol; 369 } 370 371 protected com.sun.tools.javac.tree.TreeMaker jcmake; 373 protected com.sun.tools.javac.code.Types jctypes; 374 protected JCBlock block(int flags, List<JCStatement> stats) { 375 return jcmake.Block(flags, flatten(stats)); 376 } 377 private List<JCStatement> flatten(List<JCStatement> l) { 378 if(l==null || l.isEmpty()) 379 return List.<JCStatement>nil(); 380 List<JCStatement> tail = flatten(l.tail); 381 if(l.head instanceof JCBlock) { 382 List<JCStatement> sub = flatten(((JCBlock)l.head).stats); 383 384 if(tail.isEmpty()) return sub; 385 findVarDef: { 386 for(List<JCStatement> ss = sub; ss.nonEmpty(); ss = ss.tail) 387 if(ss.head instanceof JCVariableDecl) break findVarDef; 388 return tail.prependList(sub); 389 } 390 } 391 if(isEmpty(l.head)) return tail; 392 if(l.tail==tail) return l; 393 return tail.prepend(l.head); 394 } 395 396 public static <T extends Tree> List<T> slice(List<T> head, int len, List<T> tail) { 397 return len<=0 || head.isEmpty() ? tail : slice(head.tail,len-1,tail).prepend(head.head); 398 } 399 401 protected static final Object unknownValue = new Object (); 402 protected abstract void initializeKeywords() throws ClassNotFoundException ; 403 protected Keywords keywords; 404 protected ClassReader classes; 405 protected Name.Table names; 406 protected Name nullName; 407 protected Name trueName; 408 protected Name falseName; 409 protected Symtab symtab; 410 protected static final Integer intZero = new Integer (0); 411 private EngineEnvironment ee; 412 } 413 | Popular Tags |