-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from joxad/anno
Anno
- Loading branch information
Showing
41 changed files
with
842 additions
and
121 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<module external.linked.project.id=":annotation" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="easydatabinding" external.system.module.version="unspecified" type="JAVA_MODULE" version="4"> | ||
<component name="FacetManager"> | ||
<facet type="android-gradle" name="Android-Gradle"> | ||
<configuration> | ||
<option name="GRADLE_PROJECT_PATH" value=":annotation" /> | ||
</configuration> | ||
</facet> | ||
<facet type="java-gradle" name="Java-Gradle"> | ||
<configuration> | ||
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" /> | ||
<option name="BUILDABLE" value="true" /> | ||
</configuration> | ||
</facet> | ||
</component> | ||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false"> | ||
<output url="file://$MODULE_DIR$/build/classes/main" /> | ||
<output-test url="file://$MODULE_DIR$/build/classes/test" /> | ||
<exclude-output /> | ||
<content url="file://$MODULE_DIR$"> | ||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> | ||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> | ||
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" /> | ||
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" /> | ||
<excludeFolder url="file://$MODULE_DIR$/.gradle" /> | ||
<excludeFolder url="file://$MODULE_DIR$/build" /> | ||
</content> | ||
<orderEntry type="inheritedJdk" /> | ||
<orderEntry type="sourceFolder" forTests="false" /> | ||
<orderEntry type="library" exported="" name="annotation.annotation" level="project" /> | ||
</component> | ||
</module> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
apply plugin: 'java' | ||
apply plugin: 'maven' | ||
|
||
// This is important for publishing, even if Android Studio claims it isn't | ||
// used. Android can't interpret Java 8 byte code. | ||
sourceCompatibility = JavaVersion.VERSION_1_7 | ||
targetCompatibility = JavaVersion.VERSION_1_7 |
8 changes: 8 additions & 0 deletions
8
annotation/src/main/java/com/joxad/easydatabinding/DataBindable.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.joxad.easydatabinding; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Target; | ||
|
||
@Target(value = ElementType.TYPE) | ||
public @interface DataBindable { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
apply plugin: 'java' | ||
|
||
sourceCompatibility = JavaVersion.VERSION_1_7 | ||
targetCompatibility = JavaVersion.VERSION_1_7 | ||
|
||
dependencies { | ||
compile project (':annotation') | ||
compile 'com.google.auto.service:auto-service:1.0-rc2' | ||
compile 'com.squareup:javapoet:1.0.0' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<module external.linked.project.id=":compiler" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="easydatabinding" external.system.module.version="unspecified" type="JAVA_MODULE" version="4"> | ||
<component name="FacetManager"> | ||
<facet type="android-gradle" name="Android-Gradle"> | ||
<configuration> | ||
<option name="GRADLE_PROJECT_PATH" value=":compiler" /> | ||
</configuration> | ||
</facet> | ||
<facet type="java-gradle" name="Java-Gradle"> | ||
<configuration> | ||
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" /> | ||
<option name="BUILDABLE" value="true" /> | ||
</configuration> | ||
</facet> | ||
</component> | ||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false"> | ||
<output url="file://$MODULE_DIR$/build/classes/main" /> | ||
<output-test url="file://$MODULE_DIR$/build/classes/test" /> | ||
<exclude-output /> | ||
<content url="file://$MODULE_DIR$"> | ||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> | ||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> | ||
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" /> | ||
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" /> | ||
<excludeFolder url="file://$MODULE_DIR$/.gradle" /> | ||
<excludeFolder url="file://$MODULE_DIR$/build" /> | ||
</content> | ||
<orderEntry type="inheritedJdk" /> | ||
<orderEntry type="sourceFolder" forTests="false" /> | ||
<orderEntry type="module" module-name="annotation" exported="" /> | ||
<orderEntry type="library" exported="" name="auto-service-1.0-rc2" level="project" /> | ||
<orderEntry type="library" exported="" name="javapoet-1.0.0" level="project" /> | ||
<orderEntry type="library" exported="" name="auto-common-0.3" level="project" /> | ||
<orderEntry type="library" exported="" name="guava-18.0" level="project" /> | ||
<orderEntry type="library" exported="" name="compiler.compiler" level="project" /> | ||
</component> | ||
</module> |
22 changes: 22 additions & 0 deletions
22
compiler/src/main/java/com/joxad/easydatabinding/AnnotatedClass.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.joxad.easydatabinding; | ||
|
||
import java.util.List; | ||
|
||
import javax.lang.model.element.TypeElement; | ||
import javax.lang.model.type.TypeMirror; | ||
|
||
class AnnotatedClass { | ||
public final String annotatedClassName; | ||
public final List<String> variableNames; | ||
public final TypeElement typeElement; | ||
|
||
public AnnotatedClass(TypeElement typeElement, List<String> variableNames) { | ||
this.annotatedClassName = typeElement.getSimpleName().toString(); | ||
this.variableNames = variableNames; | ||
this.typeElement = typeElement; | ||
} | ||
|
||
public TypeMirror getType() { | ||
return typeElement.asType(); | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
compiler/src/main/java/com/joxad/easydatabinding/ClassValidator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package com.joxad.easydatabinding; | ||
|
||
import javax.lang.model.element.TypeElement; | ||
|
||
import static javax.lang.model.element.Modifier.ABSTRACT; | ||
import static javax.lang.model.element.Modifier.PUBLIC; | ||
final class ClassValidator { | ||
static boolean isPublic(TypeElement annotatedClass) { | ||
return annotatedClass.getModifiers().contains(PUBLIC); | ||
} | ||
|
||
static boolean isAbstract(TypeElement annotatedClass) { | ||
return annotatedClass.getModifiers().contains(ABSTRACT); | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
compiler/src/main/java/com/joxad/easydatabinding/CodeGenerator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package com.joxad.easydatabinding; | ||
|
||
import com.squareup.javapoet.MethodSpec; | ||
import com.squareup.javapoet.TypeSpec; | ||
|
||
import java.util.List; | ||
|
||
import static com.squareup.javapoet.ClassName.get; | ||
import static com.squareup.javapoet.MethodSpec.methodBuilder; | ||
import static com.squareup.javapoet.TypeSpec.classBuilder; | ||
import static javax.lang.model.element.Modifier.FINAL; | ||
import static javax.lang.model.element.Modifier.PUBLIC; | ||
import static javax.lang.model.element.Modifier.STATIC; | ||
|
||
final class CodeGenerator { | ||
|
||
private static final String CLASS_NAME = "DataBindableUtil"; | ||
|
||
public static TypeSpec generateClass(List<AnnotatedClass> classes) { | ||
TypeSpec.Builder builder = classBuilder(CLASS_NAME) | ||
.addModifiers(PUBLIC, FINAL); | ||
for (AnnotatedClass anno : classes) { | ||
builder.addMethod(makeCreateStringMethod(anno)); | ||
} | ||
return builder.build(); | ||
} | ||
|
||
/** | ||
* @return a createString() method that takes annotatedClass's type as an input. | ||
*/ | ||
private static MethodSpec makeCreateStringMethod(AnnotatedClass annotatedClass) { | ||
StringBuilder builder = new StringBuilder(); | ||
builder.append(String.format("return \"%s{\" + ", annotatedClass.annotatedClassName)); | ||
for (String variableName : annotatedClass.variableNames) { | ||
builder.append(String.format(" \"%s='\" + String.valueOf(instance.%s) + \"',\" + ", | ||
variableName, variableName)); | ||
} | ||
builder.append("\"}\""); | ||
return methodBuilder("createString") | ||
.addJavadoc("@return string suitable for {@param instance}'s toString()") | ||
.addModifiers(PUBLIC, STATIC) | ||
.addParameter(get(annotatedClass.getType()), "instance") | ||
.addStatement(builder.toString()) | ||
.returns(String.class) | ||
.build(); | ||
} | ||
} |
117 changes: 117 additions & 0 deletions
117
compiler/src/main/java/com/joxad/easydatabinding/DataBindableProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package com.joxad.easydatabinding; | ||
|
||
import com.google.auto.service.AutoService; | ||
import com.squareup.javapoet.JavaFile; | ||
import com.squareup.javapoet.TypeSpec; | ||
|
||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
import javax.annotation.processing.*; | ||
import javax.annotation.processing.Messager; | ||
import javax.lang.model.SourceVersion; | ||
import javax.lang.model.element.Element; | ||
import javax.lang.model.element.TypeElement; | ||
import javax.lang.model.element.VariableElement; | ||
|
||
import static com.squareup.javapoet.JavaFile.builder; | ||
import static java.util.Collections.singleton; | ||
import static javax.lang.model.SourceVersion.latestSupported; | ||
import static javax.tools.Diagnostic.Kind.*; | ||
|
||
|
||
@AutoService(Processor.class) | ||
public class DataBindableProcessor extends AbstractProcessor { | ||
|
||
private static final String ANNOTATION = "@" + DataBindable.class.getSimpleName(); | ||
|
||
private Messager messager; | ||
|
||
@Override | ||
public synchronized void init(ProcessingEnvironment processingEnv) { | ||
super.init(processingEnv); | ||
messager = processingEnv.getMessager(); | ||
} | ||
|
||
@Override | ||
public Set<String> getSupportedAnnotationTypes() { | ||
return singleton(DataBindableProcessor.class.getCanonicalName()); | ||
} | ||
|
||
@Override | ||
public SourceVersion getSupportedSourceVersion() { | ||
return latestSupported(); | ||
} | ||
|
||
@Override | ||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { | ||
ArrayList<com.joxad.easydatabinding.AnnotatedClass> annotatedClasses = new ArrayList<>(); | ||
for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(DataBindable.class)) { | ||
// Our annotation is defined with @Target(value=TYPE). Therefore, we can assume that | ||
// this annotatedElement is a TypeElement. | ||
TypeElement annotatedClass = (TypeElement) annotatedElement; | ||
if (!isValidClass(annotatedClass)) { | ||
return true; | ||
} | ||
try { | ||
annotatedClasses.add(buildAnnotatedClass(annotatedClass)); | ||
} catch (NoPackageNameException | IOException e) { | ||
String message = String.format("Couldn't process class %s: %s", annotatedClass, | ||
e.getMessage()); | ||
messager.printMessage(ERROR, message, annotatedElement); | ||
} | ||
} | ||
try { | ||
generate(annotatedClasses); | ||
} catch (NoPackageNameException | IOException e) { | ||
messager.printMessage(ERROR, "Couldn't generate class"); | ||
} | ||
return true; | ||
} | ||
|
||
private boolean isValidClass(TypeElement annotatedClass) { | ||
|
||
if (!ClassValidator.isPublic(annotatedClass)) { | ||
String message = String.format("Classes annotated with %s must be public.", | ||
ANNOTATION); | ||
messager.printMessage(ERROR, message, annotatedClass); | ||
return false; | ||
} | ||
|
||
if (ClassValidator.isAbstract(annotatedClass)) { | ||
String message = String.format("Classes annotated with %s must not be abstract.", | ||
ANNOTATION); | ||
messager.printMessage(ERROR, message, annotatedClass); | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
private com.joxad.easydatabinding.AnnotatedClass buildAnnotatedClass(TypeElement annotatedClass) | ||
throws NoPackageNameException, IOException { | ||
ArrayList<String> variableNames = new ArrayList<>(); | ||
for (Element element : annotatedClass.getEnclosedElements()) { | ||
if (!(element instanceof VariableElement)) { | ||
continue; | ||
} | ||
VariableElement variableElement = (VariableElement) element; | ||
variableNames.add(variableElement.getSimpleName().toString()); | ||
} | ||
return new com.joxad.easydatabinding.AnnotatedClass(annotatedClass, variableNames); | ||
} | ||
|
||
private void generate(List<com.joxad.easydatabinding.AnnotatedClass> annos) throws NoPackageNameException, IOException { | ||
if (annos.size() == 0) { | ||
return; | ||
} | ||
String packageName = Utils.getPackageName(processingEnv.getElementUtils(), | ||
annos.get(0).typeElement); | ||
TypeSpec generatedClass = com.joxad.easydatabinding.CodeGenerator.generateClass(annos); | ||
|
||
JavaFile javaFile = builder(packageName, generatedClass).build(); | ||
javaFile.writeTo(processingEnv.getFiler()); | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
compiler/src/main/java/com/joxad/easydatabinding/NoPackageNameException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.joxad.easydatabinding; | ||
|
||
import javax.lang.model.element.TypeElement; | ||
|
||
class NoPackageNameException extends Exception { | ||
|
||
public NoPackageNameException(TypeElement typeElement) { | ||
super("The package of " + typeElement.getSimpleName() + " has no name"); | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
compiler/src/main/java/com/joxad/easydatabinding/Utils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.joxad.easydatabinding; | ||
|
||
import javax.lang.model.element.PackageElement; | ||
import javax.lang.model.element.TypeElement; | ||
import javax.lang.model.util.Elements; | ||
|
||
final class Utils { | ||
|
||
private Utils() { | ||
// no instances | ||
} | ||
|
||
static String getPackageName(Elements elementUtils, TypeElement type) | ||
throws NoPackageNameException { | ||
PackageElement pkg = elementUtils.getPackageOf(type); | ||
if (pkg.isUnnamed()) { | ||
throw new NoPackageNameException(type); | ||
} | ||
return pkg.getQualifiedName().toString(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.