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.impl;
017:
018: import com.google.gwt.dev.jjs.ast.CanBeFinal;
019: import com.google.gwt.dev.jjs.ast.Context;
020: import com.google.gwt.dev.jjs.ast.JClassType;
021: import com.google.gwt.dev.jjs.ast.JField;
022: import com.google.gwt.dev.jjs.ast.JInterfaceType;
023: import com.google.gwt.dev.jjs.ast.JMethod;
024: import com.google.gwt.dev.jjs.ast.JMethodBody;
025: import com.google.gwt.dev.jjs.ast.JNullType;
026: import com.google.gwt.dev.jjs.ast.JProgram;
027: import com.google.gwt.dev.jjs.ast.JReferenceType;
028: import com.google.gwt.dev.jjs.ast.JType;
029: import com.google.gwt.dev.jjs.ast.js.JsniMethodBody;
030: import com.google.gwt.dev.util.TextOutput;
031:
032: /**
033: * Generates Java source from our AST. ToStringGenerationVisitor is for
034: * relatively short toString() results, for easy viewing in a debugger. This
035: * subclass delves into the bodies of classes, interfaces, and methods to
036: * produce the whole source tree.
037: *
038: * The goal is not to generate the input source tree. Rather, the goal is to
039: * produce a set of classes that can be pasted into an enclosing class and
040: * compiled with a standard Java compiler. In practice, there are cases that
041: * require hand-editting to actually get a full compilation, due to Java's
042: * built-in reliance on particular built-in types.
043: *
044: * Known to be broken: Our generated String, Class, and Throwable are not
045: * compatable with the real ones, which breaks string literals, class literals,
046: * try/catch/throw, and overrides of Object methods.
047: */
048: public class SourceGenerationVisitor extends ToStringGenerationVisitor {
049:
050: private static boolean isEmptyInitializer(JMethod x) {
051: return isInitializer(x)
052: && (((JMethodBody) x.getBody()).getStatements().size() == 0);
053: }
054:
055: public SourceGenerationVisitor(TextOutput textOutput) {
056: super (textOutput);
057: }
058:
059: @Override
060: public boolean visit(JClassType x, Context ctx) {
061: // All classes are deemed "static" so the monolithic compile results can be
062: // copy/pasted into a single enclosing class.
063: print(CHARS_STATIC);
064:
065: super .visit(x, ctx);
066:
067: openBlock();
068:
069: for (int i = 0; i < x.fields.size(); ++i) {
070: JField it = x.fields.get(i);
071: accept(it);
072: newline();
073: newline();
074: }
075: for (int i = 0; i < x.methods.size(); ++i) {
076: JMethod it = x.methods.get(i);
077: if (!isEmptyInitializer(it)) {
078: accept(it);
079: newline();
080: newline();
081: }
082: }
083:
084: closeBlock();
085: return false;
086: }
087:
088: @Override
089: public boolean visit(JField x, Context ctx) {
090: super .visit(x, ctx);
091:
092: if (x.constInitializer != null) {
093: print(" = ");
094: accept(x.constInitializer);
095: }
096: semi();
097: return false;
098: }
099:
100: @Override
101: public boolean visit(JInterfaceType x, Context ctx) {
102: super .visit(x, ctx);
103:
104: openBlock();
105:
106: for (int i = 0; i < x.fields.size(); ++i) {
107: JField field = x.fields.get(i);
108: accept(field);
109: newline();
110: newline();
111: }
112: for (int i = 0; i < x.methods.size(); ++i) {
113: JMethod method = x.methods.get(i);
114: accept(method);
115: newline();
116: newline();
117: }
118:
119: closeBlock();
120: return false;
121: }
122:
123: @Override
124: public boolean visit(JProgram x, Context ctx) {
125: for (int i = 0; i < x.entryMethods.size(); ++i) {
126: JMethod method = x.entryMethods.get(i);
127: accept(method);
128: newline();
129: newline();
130: }
131: for (int i = 0; i < x.getDeclaredTypes().size(); ++i) {
132: JReferenceType type = x.getDeclaredTypes().get(i);
133: accept(type);
134: newline();
135: newline();
136: }
137: return false;
138: }
139:
140: @Override
141: public boolean visit(JsniMethodBody x, Context ctx) {
142: print("/*-");
143: String jsniCode = x.getFunc().getBody().toString();
144: String[] splits = jsniCode.split("\r|\n");
145: for (int i = 0, c = splits.length; i < c; ++i) {
146: if (i > 0) {
147: newline();
148: }
149: print(splits[i]);
150: }
151: print("-*/");
152: semi();
153: return false;
154: }
155:
156: @Override
157: protected void printMemberFinalFlag(CanBeFinal x) {
158: // suppress final flags
159: }
160:
161: @Override
162: protected void printTypeName(JType type) {
163: if (type instanceof JNullType) {
164: print("Object");
165: } else {
166: super .printTypeName(type);
167: }
168: }
169:
170: @Override
171: protected boolean shouldPrintMethodBody() {
172: return true;
173: }
174:
175: }
|