KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > java > source > script > GeneratedMatcher


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

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 JavaDoc,Object JavaDoc> {
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 JavaDoc 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 JavaDoc 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 JavaDoc s) {
90     attach(containingStatement(),s);
91     }
92     public Tree parent() {
93     return depth>1 ? parentChain[depth-2] : null;
94     }
95     @Override JavaDoc
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 JavaDoc
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 JavaDoc e) {
129             throw new RulesParseException("cannot find class: " + e.getMessage());
130         }
131     rewriter = new ImmutableTreeTranslator() {
132             @Override JavaDoc
133             public Tree visitCompilationUnit(CompilationUnitTree node, Object JavaDoc p) {
134                 currentTopLevel = (JCCompilationUnit)node;
135                 Tree result = super.visitCompilationUnit(node, p);
136                 currentTopLevel = null;
137                 return result;
138             }
139             @Override JavaDoc
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                     /* The above test checks for whether the rewrite method made
151                      * a change, and not just the super.translate(). All parents
152                      * of a changed tree will be rewritten, but we only want to
153                      * log and commit the script changes.
154                      */

155                     addResult(super.currentSym, ret, comment);
156                     changes.rewrite(tree, ret);
157                     if (ret != null)
158                         model.setPos(ret, Query.NOPOS); // mark as modified
159
}
160                 return ret;
161             }
162             @Override JavaDoc
163             public Tree visitExpressionStatement(ExpressionStatementTree node, Object JavaDoc 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 JavaDoc
184             public <T extends Tree> T translateClassRef(T tree) {
185                 tree = (T)translate(tree);
186
187                 // only import statements have packages for the currentSym
188
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) // true for package ids and imports
195
sym = model.getElement(currentTopLevel.getTypeDecls().get(0)); // use first class
196
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 JavaDoc opGT(Object JavaDoc a, Object JavaDoc b) {
268     return Boolean.valueOf(compare(a,b)>0);
269     }
270     protected Object JavaDoc opGE(Object JavaDoc a, Object JavaDoc b) {
271     return Boolean.valueOf(compare(a,b)>=0);
272     }
273     protected Object JavaDoc opLT(Object JavaDoc a, Object JavaDoc b) {
274     return Boolean.valueOf(compare(b,a)>0);
275     }
276     protected Object JavaDoc opLE(Object JavaDoc a, Object JavaDoc b) {
277     return Boolean.valueOf(compare(b,a)>=0);
278     }
279     protected Object JavaDoc opEQ(Object JavaDoc a, Object JavaDoc b) {
280     return Boolean.valueOf(compare(a,b)==0);
281     }
282     protected Object JavaDoc opNE(Object JavaDoc a, Object JavaDoc b) {
283     return Boolean.valueOf(compare(a,b)!=0);
284     }
285     protected Object JavaDoc findClass(String JavaDoc jar, String JavaDoc 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 JavaDoc 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         // discard the package and any outerclasses
317
return jcmake.Ident(sym);
318     return tree;
319     }
320     
321     protected Symbol.ClassSymbol resolveClass(Name name) throws ClassNotFoundException JavaDoc {
322         Symbol sym = resolveIdent(name);
323         if (sym instanceof Symbol.ClassSymbol)
324             return (Symbol.ClassSymbol)sym;
325         throw new ClassNotFoundException JavaDoc(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     /*
347      * From JavacCompiler
348      */

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     //FIXME: remove when TransformParser outputs com.sun.source.tree compatible files
372
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     //FIXME
400

401     protected static final Object JavaDoc unknownValue = new Object JavaDoc();
402     protected abstract void initializeKeywords() throws ClassNotFoundException JavaDoc;
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 JavaDoc intZero = new Integer JavaDoc(0);
411     private EngineEnvironment ee;
412 }
413
Popular Tags