KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > ruby > TypeAnalyzer


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 package org.netbeans.modules.ruby;
20
21 import java.util.HashMap JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.Map JavaDoc;
24
25 import org.jruby.ast.ArrayNode;
26 import org.jruby.ast.BignumNode;
27 import org.jruby.ast.CallNode;
28 import org.jruby.ast.ClassVarAsgnNode;
29 import org.jruby.ast.Colon2Node;
30 import org.jruby.ast.FalseNode;
31 import org.jruby.ast.FixnumNode;
32 import org.jruby.ast.FloatNode;
33 import org.jruby.ast.GlobalAsgnNode;
34 import org.jruby.ast.HashNode;
35 import org.jruby.ast.InstAsgnNode;
36 import org.jruby.ast.LocalAsgnNode;
37 import org.jruby.ast.NilNode;
38 import org.jruby.ast.Node;
39 import org.jruby.ast.RegexpNode;
40 import org.jruby.ast.StrNode;
41 import org.jruby.ast.SymbolNode;
42 import org.jruby.ast.TrueNode;
43 import org.jruby.ast.types.INameNode;
44
45
46 /**
47  * Perform type analysis on a given AST tree, attempting to provide a type
48  * associated with each variable, field etc.
49  *
50  * @author Tor Norbye
51  */

52 public class TypeAnalyzer {
53     /** Map from variable or field(etc) name to type. */
54     private Map JavaDoc<String JavaDoc, String JavaDoc> types;
55     private int offset;
56     private Node root;
57
58     /** Creates a new instance of TypeAnalyzer for a given position.
59      * The {@link #analyze} method can */

60     public TypeAnalyzer(Node root, int offset) {
61         this.root = root;
62         this.offset = offset;
63     }
64
65     /**
66      * Analyze the given code block down to the given offset. The {@link #getType}
67      * method can then be used to read out the symbol type if any at that point.
68      */

69     private void analyze(Node node) {
70         // Avoid including definitions appearing later in the
71
// context than the caret. (This only works for local variable
72
// analysis; for fields it could be complicated by code earlier
73
// than the caret calling code later than the caret which initializes
74
// the fild...
75
if (node.getPosition().getStartOffset() > offset) {
76             return;
77         }
78
79         // Algorithm: walk AST and look for assignments and such.
80
// Attempt to compute the type of each expression and
81
if (node instanceof LocalAsgnNode || node instanceof InstAsgnNode ||
82                 node instanceof GlobalAsgnNode || node instanceof ClassVarAsgnNode) {
83             String JavaDoc type = expressionType(node);
84
85             if (type != null) {
86                 String JavaDoc symbol = ((INameNode)node).getName();
87                 types.put(symbol, type);
88             }
89         }
90
91         @SuppressWarnings JavaDoc("unchecked")
92         List JavaDoc<Node> list = node.childNodes();
93
94         for (Node child : list) {
95             analyze(child);
96         }
97     }
98
99     /** Called on AsgnNodes to compute RHS */
100     private String JavaDoc expressionType(Node node) {
101         // If it's a simple assignment, e.g. "= 5" it will have a single
102
// child node
103
// If it's a method call, it's slightly more complicated:
104
// x = String.new("Whatever")
105
// gives me a LocalAsgnNode with a Call node child with name "new",
106
// and a ConstNode receiver (could be a composite too)
107
@SuppressWarnings JavaDoc("unchecked")
108         List JavaDoc<Node> list = node.childNodes();
109
110         if (list.size() != 1) {
111             return null;
112         }
113
114         Node child = list.get(0);
115
116         if (child instanceof CallNode) {
117             CallNode call = (CallNode)child;
118
119             // If you call Foo.new I'm going to assume the type of the expression if "Foo"
120
if ("new".equals(call.getName())) { // NOI18N
121

122                 Node receiver = call.getReceiverNode();
123
124                 if (receiver instanceof Colon2Node) {
125                     return AstUtilities.getFqn((Colon2Node)receiver);
126                 } else if (receiver instanceof INameNode) {
127                     // TODO - compute fqn (packages etc.)
128
return ((INameNode)receiver).getName();
129                 }
130             }
131         } else if (child instanceof ArrayNode) {
132             return "Array";
133         } else if (child instanceof StrNode) {
134             return "String";
135         } else if (child instanceof FixnumNode) {
136             return "Fixnum";
137         } else if (child instanceof BignumNode) {
138             return "Bignum";
139         } else if (child instanceof HashNode) {
140             return "Hash";
141         } else if (child instanceof RegexpNode) {
142             return "Regexp";
143         } else if (child instanceof SymbolNode) {
144             return "Symbol";
145         } else if (child instanceof FloatNode) {
146             return "Float";
147         } else if (child instanceof NilNode) {
148             return "NilClass";
149         } else if (child instanceof TrueNode) {
150             return "TrueClass";
151         } else if (child instanceof FalseNode) {
152             return "FalseClass";
153
154             //} else if (child instanceof RangeNode) {
155
// return "Range";
156
}
157
158         return null;
159     }
160
161     public String JavaDoc getType(String JavaDoc symbol) {
162         if (types == null) {
163             types = new HashMap JavaDoc<String JavaDoc, String JavaDoc>();
164             analyze(root);
165         }
166
167         return types.get(symbol);
168     }
169 }
170
Popular Tags