aboutsummaryrefslogtreecommitdiffstats
path: root/codegen
diff options
context:
space:
mode:
authorTom Powell <zifnab@zifnab06.net>2015-10-08 21:40:00 -0700
committerTom Powell <zifnab@zifnab06.net>2015-10-08 21:40:00 -0700
commit4bc2ec0628f74bc24c3820951f4ca2c91e516f7a (patch)
tree3b0061fa2a6be32d1fdab9a63495aacf2bdc705c /codegen
parentca8ca14e5e1904db81f4f68445b94040293d83e8 (diff)
parent5d414d68ea79cc01bdd574656099a08228b82aa2 (diff)
downloadandroid_external_gson-cm-13.0.tar.gz
android_external_gson-cm-13.0.tar.bz2
android_external_gson-cm-13.0.zip
[maven-release-plugin] copy for tag gson-2.4 Change-Id: Id89b6397c7e9152eaab6f4753826708330d7373c
Diffstat (limited to 'codegen')
-rw-r--r--codegen/pom.xml182
-rw-r--r--codegen/src/main/java/com/google/gson/codegen/CodeGen.java53
-rw-r--r--codegen/src/main/java/com/google/gson/codegen/GeneratedTypeAdapter.java21
-rw-r--r--codegen/src/main/java/com/google/gson/codegen/GeneratedTypeAdapterProcessor.java61
-rw-r--r--codegen/src/main/java/com/google/gson/codegen/JavaWriter.java443
-rw-r--r--codegen/src/main/resources/META-INF/services/javax.annotation.processing.Processor1
-rw-r--r--codegen/src/test/java/com/google/gson/codegen/functional/CodeGenFunctionalTest.java26
-rw-r--r--codegen/src/test/java/com/google/gson/codegen/functional/Order.java37
8 files changed, 824 insertions, 0 deletions
diff --git a/codegen/pom.xml b/codegen/pom.xml
new file mode 100644
index 00000000..c2f9499a
--- /dev/null
+++ b/codegen/pom.xml
@@ -0,0 +1,182 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson-codegen</artifactId>
+ <packaging>jar</packaging>
+ <version>1.0-SNAPSHOT</version>
+ <inceptionYear>2008</inceptionYear>
+ <name>Gson Code Gen</name>
+ <parent>
+ <groupId>org.sonatype.oss</groupId>
+ <artifactId>oss-parent</artifactId>
+ <version>7</version>
+ </parent>
+ <url>http://code.google.com/p/google-gson/</url>
+ <description>Google Gson grab bag of utilities, type adapters, etc.</description>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <licenses>
+ <license>
+ <name>The Apache Software License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+ <scm>
+ <connection>scm:svn:http://google-gson.googlecode.com/svn/trunk/extras</connection>
+ <developerConnection>scm:svn:https://google-gson.googlecode.com/svn/trunk/extras</developerConnection>
+ <url>http://google-gson.codegoogle.com/svn/trunk/extras</url>
+ </scm>
+ <issueManagement>
+ <system>Google Code Issue Tracking</system>
+ <url>http://code.google.com/p/google-gson/issues/list</url>
+ </issueManagement>
+ <organization>
+ <name>Google, Inc.</name>
+ <url>http://www.google.com</url>
+ </organization>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.2</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <profiles>
+ <!-- Activate PGP signing only when performing a release -->
+ <profile>
+ <id>release-sign-artifacts</id>
+ <activation>
+ <property>
+ <name>performRelease</name>
+ <value>true</value>
+ </property>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-gpg-plugin</artifactId>
+ <version>1.4</version>
+ <executions>
+ <execution>
+ <id>sign-artifacts</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>sign</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+ <build>
+ <defaultGoal>package</defaultGoal>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.5.1</version>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ <compilerArgument>-proc:none</compilerArgument>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <archive>
+ <addMavenDescriptor>false</addMavenDescriptor>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>2.1.2</version>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.8.1</version>
+ <executions>
+ <execution>
+ <id>attach-javadocs</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <links>
+ <link>http://download.oracle.com/javase/1.5.0/docs/api/</link>
+ </links>
+ <version>true</version>
+ <show>public</show>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-eclipse-plugin</artifactId>
+ <version>2.9</version>
+ <configuration>
+ <downloadSources>true</downloadSources>
+ <downloadJavadocs>true</downloadJavadocs>
+ <workspace>
+ ../eclipse-ws/
+ </workspace>
+ <workspaceCodeStylesURL>
+ file:///${basedir}/../lib/gson-formatting-styles.xml
+ </workspaceCodeStylesURL>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-release-plugin</artifactId>
+ <!-- version>2.3.2</version -->
+ <configuration>
+ <arguments>-DenableCiProfile=true</arguments>
+ <tagBase>https://google-gson.googlecode.com/svn/tags/</tagBase>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <developers>
+ <developer>
+ <name>Inderjeet Singh</name>
+ <organization>Trymph Inc.</organization>
+ </developer>
+ <developer>
+ <name>Joel Leitch</name>
+ <organization>Google Inc.</organization>
+ </developer>
+ <developer>
+ <name>Jesse Wilson</name>
+ <organization>Square Inc.</organization>
+ </developer>
+ </developers>
+</project>
diff --git a/codegen/src/main/java/com/google/gson/codegen/CodeGen.java b/codegen/src/main/java/com/google/gson/codegen/CodeGen.java
new file mode 100644
index 00000000..011568ff
--- /dev/null
+++ b/codegen/src/main/java/com/google/gson/codegen/CodeGen.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 Square, 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.gson.codegen;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+
+public class CodeGen {
+ private CodeGen() {
+ }
+
+ public static PackageElement getPackage(Element type) {
+ while (type.getKind() != ElementKind.PACKAGE) {
+ type = type.getEnclosingElement();
+ }
+ return (PackageElement) type;
+ }
+
+ /**
+ * Returns a fully qualified class name to complement {@code type}.
+ */
+ public static String adapterName(TypeElement typeElement, String suffix) {
+ StringBuilder builder = new StringBuilder();
+ rawTypeToString(builder, typeElement, '$');
+ builder.append(suffix);
+ return builder.toString();
+ }
+
+ static void rawTypeToString(StringBuilder result, TypeElement type, char innerClassSeparator) {
+ String packageName = getPackage(type).getQualifiedName().toString();
+ String qualifiedName = type.getQualifiedName().toString();
+ result.append(packageName);
+ result.append('.');
+ result.append(
+ qualifiedName.substring(packageName.length() + 1).replace('.', innerClassSeparator));
+ }
+}
diff --git a/codegen/src/main/java/com/google/gson/codegen/GeneratedTypeAdapter.java b/codegen/src/main/java/com/google/gson/codegen/GeneratedTypeAdapter.java
new file mode 100644
index 00000000..1694d88a
--- /dev/null
+++ b/codegen/src/main/java/com/google/gson/codegen/GeneratedTypeAdapter.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2012 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.gson.codegen;
+
+public @interface GeneratedTypeAdapter {
+ Class<?>[] value() default {};
+}
diff --git a/codegen/src/main/java/com/google/gson/codegen/GeneratedTypeAdapterProcessor.java b/codegen/src/main/java/com/google/gson/codegen/GeneratedTypeAdapterProcessor.java
new file mode 100644
index 00000000..cd542bc3
--- /dev/null
+++ b/codegen/src/main/java/com/google/gson/codegen/GeneratedTypeAdapterProcessor.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 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.gson.codegen;
+
+import static java.lang.reflect.Modifier.FINAL;
+
+import java.io.IOException;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedSourceVersion;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+import javax.tools.JavaFileObject;
+
+@SupportedAnnotationTypes("com.google.gson.codegen.GeneratedTypeAdapter")
+@SupportedSourceVersion(SourceVersion.RELEASE_6)
+public final class GeneratedTypeAdapterProcessor extends AbstractProcessor {
+ @Override public boolean process(Set<? extends TypeElement> types, RoundEnvironment env) {
+ System.out.println("invoked GeneratedTypeAdapterProcessor");
+ try {
+ for (Element element : env.getElementsAnnotatedWith(GeneratedTypeAdapter.class)) {
+ writeAdapter((TypeElement) element);
+ }
+ } catch (IOException e) {
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage());
+ }
+ return true;
+ }
+
+ private void writeAdapter(TypeElement type) throws IOException {
+ String typeAdapterName = CodeGen.adapterName(type, "$TypeAdapter");
+ JavaFileObject sourceFile = processingEnv.getFiler()
+ .createSourceFile(typeAdapterName, type);
+ System.out.println("Generating type adapter: " + typeAdapterName + " in " + sourceFile.getName());
+
+ JavaWriter writer = new JavaWriter(sourceFile.openWriter());
+ writer.addPackage(CodeGen.getPackage(type).getQualifiedName().toString());
+ writer.beginType(typeAdapterName, "class", FINAL, null);
+ writer.endType();
+ writer.close();
+ }
+}
diff --git a/codegen/src/main/java/com/google/gson/codegen/JavaWriter.java b/codegen/src/main/java/com/google/gson/codegen/JavaWriter.java
new file mode 100644
index 00000000..ccba6c8c
--- /dev/null
+++ b/codegen/src/main/java/com/google/gson/codegen/JavaWriter.java
@@ -0,0 +1,443 @@
+/**
+ * Copyright (C) 2012 Square, 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.gson.codegen;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Emits Java source files.
+ */
+public final class JavaWriter {
+ private static final Pattern TYPE_PATTERN = Pattern.compile("(?:[\\w$]+\\.)*([\\w$]+)");
+ private static final String INDENT = " ";
+
+ /** Map fully qualified type names to their short names. */
+ private final Map<String, String> importedTypes = new HashMap<String, String>();
+
+ private String packagePrefix;
+ private final List<Scope> scopes = new ArrayList<Scope>();
+ private final Writer out;
+
+ /**
+ * @param out the stream to which Java source will be written. This should be
+ * a buffered stream.
+ */
+ public JavaWriter(Writer out) {
+ this.out = out;
+ }
+
+ /**
+ * Emit a package declaration.
+ */
+ public void addPackage(String packageName) throws IOException {
+ if (this.packagePrefix != null) {
+ throw new IllegalStateException();
+ }
+ out.write("package ");
+ out.write(packageName);
+ out.write(";\n");
+ this.packagePrefix = packageName + ".";
+ }
+
+ /**
+ * Equivalent to {@code addImport(type.getName())}.
+ */
+ public void addImport(Class<?> type) throws IOException {
+ addImport(type.getName());
+ }
+
+ /**
+ * Emit an import for {@code type}. For the duration of the file, all
+ * references to this class will be automatically shortened.
+ */
+ public void addImport(String type) throws IOException {
+ Matcher matcher = TYPE_PATTERN.matcher(type);
+ if (!matcher.matches()) {
+ throw new IllegalArgumentException(type);
+ }
+ if (importedTypes.put(type, matcher.group(1)) != null) {
+ throw new IllegalArgumentException(type);
+ }
+ out.write("import ");
+ out.write(type);
+ out.write(";\n");
+ }
+
+ /**
+ * Emits a name like {@code java.lang.String} or {@code
+ * java.util.List<java.lang.String>}, shorting it with imports if
+ * possible.
+ */
+ private void type(String type) throws IOException {
+ if (this.packagePrefix == null) {
+ throw new IllegalStateException();
+ }
+
+ Matcher m = TYPE_PATTERN.matcher(type);
+ int pos = 0;
+ while (true) {
+ boolean found = m.find(pos);
+
+ // copy non-matching characters like "<"
+ int typeStart = found ? m.start() : type.length();
+ out.write(type, pos, typeStart - pos);
+
+ if (!found) {
+ break;
+ }
+
+ // copy a single class name, shortening it if possible
+ String name = m.group(0);
+ String imported;
+ if ((imported = importedTypes.get(name)) != null) {
+ out.write(imported);
+ } else if (name.startsWith(packagePrefix)
+ && name.indexOf('.', packagePrefix.length()) == -1) {
+ out.write(name.substring(packagePrefix.length()));
+ } else if (name.startsWith("java.lang.")) {
+ out.write(name.substring("java.lang.".length()));
+ } else {
+ out.write(name);
+ }
+ pos = m.end();
+ }
+ }
+
+ /**
+ * Emits a type declaration.
+ *
+ * @param kind such as "class", "interface" or "enum".
+ */
+ public void beginType(String type, String kind, int modifiers) throws IOException {
+ beginType(type, kind, modifiers, null);
+ }
+
+ /**
+ * Emits a type declaration.
+ *
+ * @param kind such as "class", "interface" or "enum".
+ * @param extendsType the class to extend, or null for no extends clause.
+ */
+ public void beginType(String type, String kind, int modifiers,
+ String extendsType, String... implementsTypes) throws IOException {
+ indent();
+ modifiers(modifiers);
+ out.write(kind);
+ out.write(" ");
+ type(type);
+ if (extendsType != null) {
+ out.write("\n");
+ indent();
+ out.write(" extends ");
+ type(extendsType);
+ }
+ if (implementsTypes.length > 0) {
+ out.write("\n");
+ indent();
+ out.write(" implements ");
+ for (int i = 0; i < implementsTypes.length; i++) {
+ if (i != 0) {
+ out.write(", ");
+ }
+ type(implementsTypes[i]);
+ }
+ }
+ out.write(" {\n");
+ pushScope(Scope.TYPE_DECLARATION);
+ }
+
+ /**
+ * Completes the current type declaration.
+ */
+ public void endType() throws IOException {
+ if (popScope() != Scope.TYPE_DECLARATION) {
+ throw new IllegalStateException();
+ }
+ indent();
+ out.write("}\n");
+ }
+
+ /**
+ * Emits a field declaration.
+ */
+ public void field(String type, String name, int modifiers) throws IOException {
+ field(type, name, modifiers, null);
+ }
+
+ public void field(String type, String name, int modifiers, String initialValue)
+ throws IOException {
+ indent();
+ modifiers(modifiers);
+ type(type);
+ out.write(" ");
+ out.write(name);
+
+ if (initialValue != null) {
+ out.write(" = ");
+ out.write(initialValue);
+ }
+ out.write(";\n");
+ }
+
+ /**
+ * Emit a method declaration.
+ *
+ * @param returnType the method's return type, or null for constructors.
+ * @param parameters alternating parameter types and names.
+ * @param name the method name, or the fully qualified class name for
+ * constructors.
+ */
+ public void beginMethod(String returnType, String name, int modifiers, String... parameters)
+ throws IOException {
+ indent();
+ modifiers(modifiers);
+ if (returnType != null) {
+ type(returnType);
+ out.write(" ");
+ out.write(name);
+ } else {
+ type(name);
+ }
+ out.write("(");
+ for (int p = 0; p < parameters.length; ) {
+ if (p != 0) {
+ out.write(", ");
+ }
+ type(parameters[p++]);
+ out.write(" ");
+ type(parameters[p++]);
+ }
+ out.write(")");
+ if ((modifiers & Modifier.ABSTRACT) != 0) {
+ out.write(";\n");
+ pushScope(Scope.ABSTRACT_METHOD);
+ } else {
+ out.write(" {\n");
+ pushScope(Scope.NON_ABSTRACT_METHOD);
+ }
+ }
+
+ /**
+ * Annotates the next element with {@code annotation}. The annotation has no
+ * attributes.
+ */
+ public void annotation(String annotation) throws IOException {
+ indent();
+ out.write("@");
+ type(annotation);
+ out.write("\n");
+ }
+
+ /**
+ * Equivalent to {@code annotation(annotationType.getName())}.
+ */
+ public void annotation(Class<? extends Annotation> annotationType) throws IOException {
+ annotation(annotationType.getName());
+ }
+
+ /**
+ * @param pattern a code pattern like "int i = %s". Shouldn't contain a
+ * trailing semicolon or newline character.
+ */
+ public void statement(String pattern, Object... args) throws IOException {
+ checkInMethod();
+ indent();
+ out.write(String.format(pattern, args));
+ out.write(";\n");
+ }
+
+ /**
+ * @param controlFlow the control flow construct and its code, such as
+ * "if (foo == 5)". Shouldn't contain braces or newline characters.
+ */
+ public void beginControlFlow(String controlFlow) throws IOException {
+ checkInMethod();
+ indent();
+ out.write(controlFlow);
+ out.write(" {\n");
+ pushScope(Scope.CONTROL_FLOW);
+ }
+
+ /**
+ * @param controlFlow the control flow construct and its code, such as
+ * "else if (foo == 10)". Shouldn't contain braces or newline characters.
+ */
+ public void nextControlFlow(String controlFlow) throws IOException {
+ if (popScope() != Scope.CONTROL_FLOW) {
+ throw new IllegalArgumentException();
+ }
+
+ indent();
+ pushScope(Scope.CONTROL_FLOW);
+ out.write("} ");
+ out.write(controlFlow);
+ out.write(" {\n");
+ }
+
+ public void endControlFlow() throws IOException {
+ endControlFlow(null);
+ }
+
+ /**
+ * @param controlFlow the optional control flow construct and its code, such
+ * as "while(foo == 20)". Only used for "do/while" control flows.
+ */
+ public void endControlFlow(String controlFlow) throws IOException {
+ if (popScope() != Scope.CONTROL_FLOW) {
+ throw new IllegalArgumentException();
+ }
+
+ indent();
+ if (controlFlow != null) {
+ out.write("} ");
+ out.write(controlFlow);
+ out.write(";\n");
+ } else {
+ out.write("}\n");
+ }
+ }
+
+ /**
+ * Completes the current method declaration.
+ */
+ public void endMethod() throws IOException {
+ Scope popped = popScope();
+ if (popped == Scope.NON_ABSTRACT_METHOD) {
+ indent();
+ out.write("}\n");
+ } else if (popped != Scope.ABSTRACT_METHOD) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Returns the string literal representing {@code data}, including wrapping
+ * quotes.
+ */
+ public static String stringLiteral(String data) {
+ StringBuilder result = new StringBuilder();
+ result.append('"');
+ for (int i = 0; i < data.length(); i++) {
+ char c = data.charAt(i);
+ switch (c) {
+ case '"':
+ result.append("\\\"");
+ break;
+ case '\\':
+ result.append("\\\\");
+ break;
+ case '\t':
+ result.append("\\\t");
+ break;
+ case '\b':
+ result.append("\\\b");
+ break;
+ case '\n':
+ result.append("\\\n");
+ break;
+ case '\r':
+ result.append("\\\r");
+ break;
+ case '\f':
+ result.append("\\\f");
+ break;
+ default:
+ result.append(c);
+ }
+ }
+ result.append('"');
+ return result.toString();
+ }
+
+ public void close() throws IOException {
+ out.close();
+ }
+
+ /**
+ * Emit modifier names.
+ */
+ private void modifiers(int modifiers) throws IOException {
+ if ((modifiers & Modifier.PUBLIC) != 0) {
+ out.write("public ");
+ }
+ if ((modifiers & Modifier.PRIVATE) != 0) {
+ out.write("private ");
+ }
+ if ((modifiers & Modifier.PROTECTED) != 0) {
+ out.write("protected ");
+ }
+ if ((modifiers & Modifier.STATIC) != 0) {
+ out.write("static ");
+ }
+ if ((modifiers & Modifier.FINAL) != 0) {
+ out.write("final ");
+ }
+ if ((modifiers & Modifier.ABSTRACT) != 0) {
+ out.write("abstract ");
+ }
+ if ((modifiers & Modifier.SYNCHRONIZED) != 0) {
+ out.write("synchronized ");
+ }
+ if ((modifiers & Modifier.TRANSIENT) != 0) {
+ out.write("transient ");
+ }
+ if ((modifiers & Modifier.VOLATILE) != 0) {
+ out.write("volatile ");
+ }
+ }
+
+ private void indent() throws IOException {
+ for (int i = 0; i < scopes.size(); i++) {
+ out.write(INDENT);
+ }
+ }
+
+ private void checkInMethod() {
+ Scope scope = peekScope();
+ if (scope != Scope.NON_ABSTRACT_METHOD && scope != Scope.CONTROL_FLOW) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ private void pushScope(Scope pushed) {
+ scopes.add(pushed);
+ }
+
+ private Scope peekScope() {
+ return scopes.get(scopes.size() - 1);
+ }
+
+ private Scope popScope() {
+ return scopes.remove(scopes.size() - 1);
+ }
+
+ private enum Scope {
+ TYPE_DECLARATION,
+ ABSTRACT_METHOD,
+ NON_ABSTRACT_METHOD,
+ CONTROL_FLOW,
+ }
+}
diff --git a/codegen/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/codegen/src/main/resources/META-INF/services/javax.annotation.processing.Processor
new file mode 100644
index 00000000..a052da0c
--- /dev/null
+++ b/codegen/src/main/resources/META-INF/services/javax.annotation.processing.Processor
@@ -0,0 +1 @@
+com.google.gson.codegen.GeneratedTypeAdapterProcessor \ No newline at end of file
diff --git a/codegen/src/test/java/com/google/gson/codegen/functional/CodeGenFunctionalTest.java b/codegen/src/test/java/com/google/gson/codegen/functional/CodeGenFunctionalTest.java
new file mode 100644
index 00000000..855ee3fa
--- /dev/null
+++ b/codegen/src/test/java/com/google/gson/codegen/functional/CodeGenFunctionalTest.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2012 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.gson.codegen.functional;
+
+import junit.framework.TestCase;
+
+public class CodeGenFunctionalTest extends TestCase {
+
+ public void testGeneratedJson() {
+ Order order = new Order("toy", 10);
+ // TODO: figure out how to access the generated type adapter
+ }
+}
diff --git a/codegen/src/test/java/com/google/gson/codegen/functional/Order.java b/codegen/src/test/java/com/google/gson/codegen/functional/Order.java
new file mode 100644
index 00000000..916587f3
--- /dev/null
+++ b/codegen/src/test/java/com/google/gson/codegen/functional/Order.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 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.gson.codegen.functional;
+
+import com.google.gson.codegen.GeneratedTypeAdapter;
+
+@GeneratedTypeAdapter
+final class Order {
+ private final String itemName;
+ private final int price;
+
+ public Order(String itemName, int price) {
+ this.itemName = itemName;
+ this.price = price;
+ }
+
+ public String getItemName() {
+ return itemName;
+ }
+
+ public int getAmount() {
+ return price;
+ }
+}