001: /*
002: * Copyright 2007 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.gwt.dev.jjs.ast;
017:
018: import com.google.gwt.dev.jjs.InternalCompilerException;
019: import com.google.gwt.dev.jjs.ast.js.JsniMethodRef;
020:
021: /**
022: * Java class literal expression.
023: */
024: public class JClassLiteral extends JLiteral {
025: private static String getClassName(String fullName) {
026: int pos = fullName.lastIndexOf(".");
027: return fullName.substring(pos + 1);
028: }
029:
030: private static String getPackageName(String fullName) {
031: int pos = fullName.lastIndexOf(".");
032: return fullName.substring(0, pos + 1);
033: }
034:
035: private static String getTypeName(JType type) {
036: String typeName;
037: if (type instanceof JArrayType) {
038: typeName = type.getJsniSignatureName().replace('/', '.');
039: } else {
040: typeName = type.getName();
041: }
042:
043: return typeName;
044: }
045:
046: private JExpression classObjectAllocation;
047: private final JType refType;
048:
049: /**
050: * These are only supposed to be constructed by JProgram.
051: */
052: JClassLiteral(JProgram program, JType type) {
053: super (program);
054: refType = type;
055:
056: String typeName = getTypeName(type);
057:
058: JMethod method = program.getIndexedMethod(type
059: .getClassLiteralFactoryMethod());
060: assert method != null;
061:
062: JMethodCall call = new JMethodCall(program, null, null, method);
063: call.getArgs().add(
064: program.getLiteralString(getPackageName(typeName)));
065: call.getArgs().add(
066: program.getLiteralString(getClassName(typeName)));
067:
068: if (type instanceof JClassType && !(type instanceof JArrayType)) {
069: /*
070: * For non-array classes and enums, determine the class literal of the
071: * supertype, if there is one. Arrays are excluded because they always
072: * have Object as their superclass.
073: */
074: assert (type instanceof JClassType);
075: JClassType classType = (JClassType) type;
076:
077: JLiteral super classLiteral;
078:
079: if (classType.extnds != null) {
080: super classLiteral = program
081: .getLiteralClass(classType.extnds);
082: } else {
083: super classLiteral = program.getLiteralNull();
084: }
085:
086: call.getArgs().add(super classLiteral);
087:
088: if (classType instanceof JEnumType) {
089: JEnumType enumType = (JEnumType) classType;
090: JMethod valuesMethod = null;
091: for (JMethod methodIt : enumType.methods) {
092: if ("values".equals(methodIt.getName())) {
093: if (methodIt.params.size() != 0) {
094: continue;
095: }
096: valuesMethod = methodIt;
097: }
098: }
099: if (valuesMethod == null) {
100: throw new InternalCompilerException(
101: "Could not find enum values() method");
102: }
103: JsniMethodRef jsniMethodRef = new JsniMethodRef(
104: program.program, null, valuesMethod);
105: call.getArgs().add(jsniMethodRef);
106: }
107: } else {
108: assert (type instanceof JArrayType
109: || type instanceof JInterfaceType || type instanceof JPrimitiveType);
110: }
111:
112: classObjectAllocation = call;
113: }
114:
115: public JType getRefType() {
116: return refType;
117: }
118:
119: public JType getType() {
120: return classObjectAllocation.getType();
121: }
122:
123: public void traverse(JVisitor visitor, Context ctx) {
124: if (visitor.visit(this, ctx)) {
125: classObjectAllocation = visitor
126: .accept(classObjectAllocation);
127: }
128: visitor.endVisit(this, ctx);
129: }
130: }
|