blob: 95ac3a6744eefac51f8f1eda163c4cb18f0be66c [file] [log] [blame]
/*
* Copyright 2006 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.user.rebind;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory.JavaSourceCategory;
import java.io.PrintWriter;
class ClassSourceFileComposer implements SourceWriter {
/**
* For the interior of a '*' style comment.
*/
private static final String STAR_COMMENT_LINE = " * ";
private boolean atStart;
/**
* Either STAR/BLOCK comment line, not pulled out into a ENUM class because
* only used by this class.
*/
private String commentIndicator;
private final GeneratorContext ctx;
/**
* Are you currently in a comment?
*/
private boolean inComment;
private int indent;
private final PrintWriter printWriter;
ClassSourceFileComposer(GeneratorContext ctx, PrintWriter printWriter,
String targetPackageName, String[] annotationDeclarations,
String targetClassShortName, String superClassName,
String[] interfaceNames, String[] imports, JavaSourceCategory category,
String classJavaDocComment) {
this.ctx = ctx;
this.printWriter = printWriter;
if (targetPackageName == null) {
throw new IllegalArgumentException("Cannot supply a null package name to"
+ targetClassShortName);
}
// TODO: support a user-specified file header
if (targetPackageName.length() > 0) {
println("package " + targetPackageName + ";");
}
if (imports != null && imports.length > 0) {
println();
for (int i = 0, n = imports.length; i < n; ++i) {
println("import " + imports[i] + ";");
}
}
if (classJavaDocComment != null) {
beginJavaDocComment();
print(classJavaDocComment);
endJavaDocComment();
} else {
// beginJavaDocComment adds its own leading newline, make up for it here.
println();
}
for (String annotation : annotationDeclarations) {
println(annotation);
}
if (category == JavaSourceCategory.CLASS) {
emitClassDecl(targetClassShortName, superClassName, interfaceNames);
} else {
emitInterfaceDecl(targetClassShortName, superClassName, interfaceNames);
}
println(" {");
indent();
}
/**
* Begin emitting a JavaDoc comment.
*/
public void beginJavaDocComment() {
println("\n/**");
inComment = true;
commentIndicator = STAR_COMMENT_LINE;
}
public void commit(TreeLogger logger) {
outdent();
println("}");
printWriter.close();
// If generating a class on the command line, may not have a
if (ctx != null) {
ctx.commit(logger, printWriter);
}
}
/**
* End emitting a JavaDoc comment.
*/
public void endJavaDocComment() {
inComment = false;
println("\n */");
}
public void indent() {
++indent;
}
public void indentln(String s) {
indent();
println(s);
outdent();
}
public void indentln(String s, Object... args) {
indentln(String.format(s, args));
}
public void outdent() {
--indent;
}
public void print(String s) {
int pos = 0;
for (;;) {
// If we just printed a newline, print an indent.
if (atStart) {
for (int j = 0; j < indent; ++j) {
printWriter.print(" ");
}
if (inComment) {
printWriter.print(commentIndicator);
}
atStart = false;
}
// Now find the next newline.
int nl = s.indexOf('\n', pos);
// If there's no newline or it's at the end of the string, just write
// the rest of the string, and we're done.
if (nl == -1 || nl == s.length() - 1) {
printWriter.write(s, pos, s.length() - pos);
return;
}
// Otherwise, write up to and including the newline, note that we just
// printed a newline, and loop on the rest of the string.
printWriter.write(s, pos, nl + 1 - pos);
atStart = true;
pos = nl + 1;
}
}
public void print(String s, Object... args) {
print(String.format(s, args));
}
public void println() {
print("\n");
atStart = true;
}
public void println(String s) {
print(s + "\n");
atStart = true;
}
public void println(String s, Object... args) {
println(String.format(s, args));
}
private void emitClassDecl(String targetClassShortName,
String superClassName, String[] interfaceNames) {
print("public class " + targetClassShortName);
if (superClassName != null) {
print(" extends " + superClassName);
}
if (interfaceNames != null && interfaceNames.length > 0) {
print(" implements ");
for (int i = 0, n = interfaceNames.length; i < n; ++i) {
if (i > 0) {
print(", ");
}
print(interfaceNames[i]);
}
}
}
private void emitInterfaceDecl(String targetClassShortName,
String superClassName, String[] interfaceNames) {
if (superClassName != null) {
throw new IllegalArgumentException("Cannot set superclass name "
+ superClassName + " on a interface.");
}
print("public interface " + targetClassShortName);
if (interfaceNames != null && interfaceNames.length > 0) {
print(" extends ");
for (int i = 0; i < interfaceNames.length; ++i) {
if (i > 0) {
print(", ");
}
print(interfaceNames[i]);
}
}
}
}