001: /*
002: * xtc - The eXTensible Compiler
003: * Copyright (C) 2006-2007 IBM Corp.
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * version 2 as published by the Free Software Foundation.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
017: * USA.
018: */
019: package xtc.lang;
020:
021: import java.lang.reflect.Constructor;
022: import java.lang.reflect.Field;
023: import java.lang.reflect.Method;
024: import java.lang.reflect.Modifier;
025: import java.util.ArrayList;
026: import java.util.List;
027:
028: import xtc.tree.Attribute;
029: import xtc.type.AliasT;
030: import xtc.type.ClassT;
031: import xtc.type.InterfaceT;
032: import xtc.type.MethodT;
033: import xtc.type.Type;
034: import xtc.type.VariableT;
035: import xtc.type.VoidT;
036: import xtc.util.SymbolTable;
037: import xtc.util.Utilities;
038:
039: /**
040: * Uses reflection to construct externally visible types and fill in the symbol
041: * table for entities for which no source code is available. This is not a
042: * visitor, but has similar method names to emphasize the similarities with
043: * JavaExternalAnalyzer.
044: *
045: * @author Martin Hirzel
046: * @version $Revision: 1.27 $
047: */
048: public final class JavaNoSourceAnalyzer {
049: public final SymbolTable _table;
050:
051: public JavaNoSourceAnalyzer(final SymbolTable table) {
052: _table = table;
053: }
054:
055: private final Type defineMethod(final List<Attribute> modifiers,
056: MethodT result, final String symbol) {
057: for (final Attribute mod : modifiers)
058: result.addAttribute(mod);
059: _table.current().define(symbol, result);
060: _table.enter(symbol);
061: result.scope(_table.current().getQualifiedName());
062: _table.exit();
063: JavaEntities.currentType(_table).getMethods().add(result);
064: assert result.isMethod();
065: return result;
066: }
067:
068: public final void visitClassBody(final Class clazz) {
069: final Class[] classes = clazz.getDeclaredClasses();
070: for (int i = 0; i < classes.length; i++)
071: visitClassOrInterface(classes[i]);
072: final Constructor[] constructors = clazz
073: .getDeclaredConstructors();
074: for (int i = 0; i < constructors.length; i++)
075: visitMethodDeclaration(constructors[i]);
076: final Field[] fields = clazz.getDeclaredFields();
077: for (int i = 0; i < fields.length; i++)
078: visitFieldDeclaration(fields[i]);
079: final Method[] methods = clazz.getDeclaredMethods();
080: for (int i = 0; i < methods.length; i++)
081: visitMethodDeclaration(methods[i]);
082: }
083:
084: private static String getQName(final Class clazz) {
085: final Class declaringClass = clazz.getDeclaringClass();
086: if (null == declaringClass)
087: return clazz.getName();
088: return Utilities.qualify(getQName(declaringClass), clazz
089: .getSimpleName());
090: }
091:
092: public final Type visitClassDeclaration(final Class clazz) {
093: if (clazz.isInterface())
094: throw new Error(clazz.getName());
095: final List<Attribute> modifiers = visitModifiers(clazz
096: .getModifiers());
097: final String canonicalName = getQName(clazz);
098: final String simpleName;
099: {
100: final String name = Utilities.getName(canonicalName);
101: final int i = name.lastIndexOf('$');
102: if (-1 == i)
103: simpleName = name;
104: else
105: simpleName = name.substring(1 + i);
106: }
107: final Type parent;
108: final Class super Class = clazz.getSuperclass();
109: if (null == super Class) {
110: parent = null;
111: if (!"java.lang.Object".equals(clazz.getName()))
112: throw new Error();
113: } else {
114: parent = visitType(clazz.getSuperclass());
115: }
116: final List<Type> interfaces = visitTypeList(clazz
117: .getInterfaces());
118: final ClassT result = new ClassT(canonicalName, parent,
119: interfaces, new ArrayList<Type>(),
120: new ArrayList<Type>());
121: for (final Attribute mod : modifiers)
122: result.addAttribute(mod);
123: final String tagName = SymbolTable.toTagName(simpleName);
124: _table.current().define(tagName, result);
125: _table.enter(simpleName);
126: result.scope(_table.current().getQualifiedName());
127: visitClassBody(clazz);
128: _table.exit();
129: assert result.isClass();
130: return result;
131: }
132:
133: public final Type visitClassOrInterface(final Class clazz) {
134: return clazz.isInterface() ? visitInterfaceDeclaration(clazz)
135: : visitClassDeclaration(clazz);
136: }
137:
138: public final Type visitFieldDeclaration(final Field field) {
139: final Type type = visitType(field.getType());
140: final VariableT result = VariableT.newField(type, field
141: .getName());
142: for (final Attribute mod : visitModifiers(field.getModifiers()))
143: result.addAttribute(mod);
144: _table.current().define(field.getName(), result);
145: result.scope(_table.current().getQualifiedName());
146: JavaEntities.currentType(_table).getFields().add(result);
147: assert JavaEntities.isFieldT(result);
148: return result;
149: }
150:
151: public final List<Type> visitFormalParameters(final Class[] types) {
152: final List<Type> result = new ArrayList<Type>(types.length);
153: for (int i = 0; i < types.length; i++) {
154: final VariableT p = VariableT.newParam(visitType(types[i]),
155: "x" + i);
156: assert JavaEntities.isParameterT(p);
157: result.add(p);
158: }
159: return result;
160: }
161:
162: public final Type visitInterfaceDeclaration(final Class interfaze) {
163: if (!interfaze.isInterface())
164: throw new Error(interfaze.getName());
165: final List<Attribute> modifiers = visitModifiers(interfaze
166: .getModifiers());
167: final String canonicalName = interfaze.getName();
168: final String simpleName;
169: {
170: final String name = Utilities.getName(canonicalName);
171: final int i = name.lastIndexOf('$');
172: if (-1 == i)
173: simpleName = name;
174: else
175: simpleName = name.substring(1 + i);
176: }
177: final List<Type> interfaces = visitTypeList(interfaze
178: .getInterfaces());
179: final InterfaceT result = new InterfaceT(canonicalName,
180: interfaces, new ArrayList<Type>(),
181: new ArrayList<Type>());
182: for (final Attribute mod : modifiers)
183: result.addAttribute(mod);
184: final String tagName = SymbolTable.toTagName(simpleName);
185: _table.current().define(tagName, result);
186: _table.enter(simpleName);
187: result.scope(_table.current().getQualifiedName());
188: visitClassBody(interfaze);
189: _table.exit();
190: assert result.isInterface();
191: return result;
192: }
193:
194: public final Type visitMethodDeclaration(final Constructor method) {
195: final List<Attribute> modifiers = visitModifiers(method
196: .getModifiers());
197: final Type base = visitType(method.getDeclaringClass());
198: final List<Type> exceptions = visitTypeList(method
199: .getExceptionTypes());
200: final String symbol = JavaEntities
201: .methodSymbolFromConstructor(method);
202: final List<Type> parameters = visitFormalParameters(method
203: .getParameterTypes());
204: final MethodT methodT = JavaEntities.newRawConstructor(base,
205: parameters, exceptions);
206: final Type result = defineMethod(modifiers, methodT, symbol);
207: return result;
208: }
209:
210: public final Type visitMethodDeclaration(final Method method) {
211: final List<Attribute> modifiers = visitModifiers(method
212: .getModifiers());
213: final Type returnType = visitType(method.getReturnType());
214: final String name = method.getName();
215: final List<Type> exceptions = visitTypeList(method
216: .getExceptionTypes());
217: final String symbol = JavaEntities
218: .methodSymbolFromMethod(method);
219: final List<Type> parameters = visitFormalParameters(method
220: .getParameterTypes());
221: final MethodT methodT = new MethodT(returnType, name,
222: parameters, false, exceptions);
223: final Type result = defineMethod(modifiers, methodT, symbol);
224: return result;
225: }
226:
227: public final List<Attribute> visitModifiers(final int modifiers) {
228: final List<Attribute> result = new ArrayList<Attribute>();
229: if (Modifier.isAbstract(modifiers))
230: result.add(JavaEntities.nameToModifier("abstract"));
231: if (Modifier.isFinal(modifiers))
232: result.add(JavaEntities.nameToModifier("final"));
233: if (Modifier.isNative(modifiers))
234: result.add(JavaEntities.nameToModifier("native"));
235: if (Modifier.isPrivate(modifiers))
236: result.add(JavaEntities.nameToModifier("private"));
237: if (Modifier.isProtected(modifiers))
238: result.add(JavaEntities.nameToModifier("protected"));
239: if (Modifier.isPublic(modifiers))
240: result.add(JavaEntities.nameToModifier("public"));
241: if (Modifier.isStatic(modifiers))
242: result.add(JavaEntities.nameToModifier("static"));
243: if (Modifier.isStrict(modifiers))
244: result.add(JavaEntities.nameToModifier("strictfp"));
245: if (Modifier.isSynchronized(modifiers))
246: result.add(JavaEntities.nameToModifier("synchronized"));
247: if (Modifier.isTransient(modifiers))
248: result.add(JavaEntities.nameToModifier("transient"));
249: if (Modifier.isVolatile(modifiers))
250: result.add(JavaEntities.nameToModifier("volatile"));
251: return result;
252: }
253:
254: public final Type visitType(final Class clazz) {
255: Class componentC = clazz;
256: int dimensions = 0;
257: while (componentC.isArray()) {
258: componentC = componentC.getComponentType();
259: dimensions++;
260: }
261: final Type componentT = componentC.isPrimitive() ? visitTypeName(componentC
262: .getName())
263: : new AliasT(componentC.getName());
264: final Type result = JavaEntities.typeWithDimensions(componentT,
265: dimensions);
266: assert JavaEntities.isReturnT(result);
267: return result;
268: }
269:
270: public final List<Type> visitTypeList(final Class[] types) {
271: final List<Type> result = new ArrayList<Type>(types.length);
272: for (int i = 0; i < types.length; i++)
273: result.add(visitType(types[i]));
274: return result;
275: }
276:
277: public final Type visitTypeName(final String name) {
278: if (1 == name.length()) {
279: switch (name.charAt(0)) {
280: case 'Z':
281: return JavaEntities.nameToBaseType("boolean");
282: case 'B':
283: return JavaEntities.nameToBaseType("byte");
284: case 'C':
285: return JavaEntities.nameToBaseType("char");
286: case 'D':
287: return JavaEntities.nameToBaseType("double");
288: case 'F':
289: return JavaEntities.nameToBaseType("float");
290: case 'I':
291: return JavaEntities.nameToBaseType("int");
292: case 'J':
293: return JavaEntities.nameToBaseType("long");
294: case 'S':
295: return JavaEntities.nameToBaseType("short");
296: }
297: }
298: final Type result = JavaEntities.nameToBaseType(name);
299: assert result.isBoolean() || result.isNumber()
300: || result instanceof VoidT;
301: return result;
302: }
303: }
|