apt 实现
This commit is contained in:
@ -8,7 +8,7 @@ dependencies {
|
||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||
compile 'com.google.auto:auto-common:0.6'
|
||||
compile 'com.google.auto.service:auto-service:1.0-rc2'
|
||||
compile 'com.squareup:javapoet:1.7.0'
|
||||
compile 'com.squareup:javapoet:1.9.0'
|
||||
compile project(':AriaAnnotations')
|
||||
|
||||
sourceCompatibility = "1.7"
|
||||
|
@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* 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.arialyy.compiler;
|
||||
|
||||
import com.arialyy.annotations.Download;
|
||||
@ -22,7 +37,7 @@ import javax.lang.model.element.TypeElement;
|
||||
@Override public synchronized void init(ProcessingEnvironment processingEnv) {
|
||||
super.init(processingEnv);
|
||||
PrintLog.init(processingEnv.getMessager());
|
||||
mHandler = new ElementHandle(processingEnv.getFiler());
|
||||
mHandler = new ElementHandle(processingEnv.getFiler(), processingEnv.getElementUtils());
|
||||
}
|
||||
|
||||
@Override public Set<String> getSupportedAnnotationTypes() {
|
||||
@ -43,7 +58,7 @@ import javax.lang.model.element.TypeElement;
|
||||
annotataions.add(Upload.onTaskComplete.class.getCanonicalName());
|
||||
annotataions.add(Upload.onTaskFail.class.getCanonicalName());
|
||||
annotataions.add(Upload.onTaskPre.class.getCanonicalName());
|
||||
annotataions.add(Upload.onTaskResume.class.getCanonicalName());
|
||||
//annotataions.add(Upload.onTaskResume.class.getCanonicalName());
|
||||
annotataions.add(Upload.onTaskRunning.class.getCanonicalName());
|
||||
annotataions.add(Upload.onTaskStart.class.getCanonicalName());
|
||||
annotataions.add(Upload.onTaskStop.class.getCanonicalName());
|
||||
@ -56,10 +71,10 @@ import javax.lang.model.element.TypeElement;
|
||||
|
||||
@Override
|
||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||
PrintLog.getInstance().info("开始扫描");
|
||||
mHandler.clean();
|
||||
mHandler.handleDownload(roundEnv);
|
||||
mHandler.handleUpload(roundEnv);
|
||||
mHandler.createProxyFile();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* 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.arialyy.compiler;
|
||||
|
||||
import com.arialyy.annotations.Download;
|
||||
import com.arialyy.annotations.Upload;
|
||||
import com.squareup.javapoet.ClassName;
|
||||
import com.squareup.javapoet.FieldSpec;
|
||||
import com.squareup.javapoet.JavaFile;
|
||||
import com.squareup.javapoet.MethodSpec;
|
||||
import com.squareup.javapoet.ParameterSpec;
|
||||
import com.squareup.javapoet.TypeSpec;
|
||||
import com.squareup.javapoet.ParameterizedTypeName;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -14,7 +36,10 @@ import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.PackageElement;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.element.VariableElement;
|
||||
import javax.lang.model.util.Elements;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2017/6/6.
|
||||
@ -23,10 +48,12 @@ import javax.lang.model.element.VariableElement;
|
||||
class ElementHandle {
|
||||
|
||||
private Filer mFiler;
|
||||
private Map<String, Set<String>> mMethods = new HashMap<>();
|
||||
private Elements mElementUtil;
|
||||
private Map<String, ProxyEntity> mMethods = new HashMap<>();
|
||||
|
||||
ElementHandle(Filer filer) {
|
||||
ElementHandle(Filer filer, Elements elements) {
|
||||
mFiler = filer;
|
||||
mElementUtil = elements;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -55,12 +82,137 @@ class ElementHandle {
|
||||
saveMethod(false, roundEnv, Upload.onTaskComplete.class);
|
||||
saveMethod(false, roundEnv, Upload.onTaskFail.class);
|
||||
saveMethod(false, roundEnv, Upload.onTaskPre.class);
|
||||
saveMethod(false, roundEnv, Upload.onTaskResume.class);
|
||||
//saveMethod(false, roundEnv, Upload.onTaskResume.class);
|
||||
saveMethod(false, roundEnv, Upload.onTaskRunning.class);
|
||||
saveMethod(false, roundEnv, Upload.onTaskStart.class);
|
||||
saveMethod(false, roundEnv, Upload.onTaskStop.class);
|
||||
}
|
||||
|
||||
void printMethods() {
|
||||
//Set<String> keys = mMethods.keySet();
|
||||
//for (String key : keys) {
|
||||
// ProxyEntity entity = mMethods.get(key);
|
||||
// for (String method : entity.methods) {
|
||||
// PrintLog.getInstance().info(method);
|
||||
// }
|
||||
//}
|
||||
PrintLog.getInstance().info("size ==> " + mMethods.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* 在build文件夹中生成如下代码的文件
|
||||
* <pre>
|
||||
* <code>
|
||||
* package com.arialyy.simple.download;
|
||||
*
|
||||
* import com.arialyy.aria.core.download.DownloadTask;
|
||||
* import com.arialyy.aria.core.scheduler.AbsSchedulerListener;
|
||||
*
|
||||
* public final class SingleTaskActivity$$DownloadListenerProxy extends
|
||||
* AbsSchedulerListener<DownloadTask> {
|
||||
* private SingleTaskActivity obj;
|
||||
*
|
||||
* public void onPre(final DownloadTask task) {
|
||||
* obj.onPre((DownloadTask)task);
|
||||
* }
|
||||
*
|
||||
* public void onTaskStart(final DownloadTask task) {
|
||||
* obj.onStart((DownloadTask)task);
|
||||
* }
|
||||
*
|
||||
* public void setListener(final SingleTaskActivity obj) {
|
||||
* this.obj = obj;
|
||||
* }
|
||||
* }
|
||||
* </code>
|
||||
* </pre>
|
||||
*/
|
||||
void createProxyFile() {
|
||||
Set<String> keys = mMethods.keySet();
|
||||
try {
|
||||
for (String key : keys) {
|
||||
ProxyEntity entity = mMethods.get(key);
|
||||
JavaFile jf = JavaFile.builder(entity.packageName, createProxyClass(entity)).build();
|
||||
|
||||
jf.writeTo(mFiler);
|
||||
// 如果需要在控制台打印生成的文件,则去掉下面的注释
|
||||
//jf.writeTo(System.out);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建代理方法
|
||||
*
|
||||
* @param isDownload 是否是下载的注解
|
||||
* @param annotation {@link Download}、{@link Upload}
|
||||
* @param methodName 被代理类注解的方法名
|
||||
*/
|
||||
private MethodSpec createProxyMethod(boolean isDownload, Class<? extends Annotation> annotation,
|
||||
String methodName) {
|
||||
ClassName task = ClassName.get(
|
||||
isDownload ? "com.arialyy.aria.core.download" : "com.arialyy.aria.core.upload",
|
||||
isDownload ? "DownloadTask" : "UploadTask");
|
||||
ParameterSpec parameterSpec =
|
||||
ParameterSpec.builder(task, "task").addModifiers(Modifier.FINAL).build();
|
||||
return MethodSpec.methodBuilder(annotation.getSimpleName())
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.returns(void.class)
|
||||
.addParameter(parameterSpec)
|
||||
.addAnnotation(Override.class)
|
||||
.addCode("obj."
|
||||
+ methodName
|
||||
+ "("
|
||||
+ (isDownload ? "(DownloadTask)" : "(UploadTask)")
|
||||
+ "task);\n")
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建代理类
|
||||
*/
|
||||
private TypeSpec createProxyClass(ProxyEntity entity) {
|
||||
TypeSpec.Builder builder = TypeSpec.classBuilder(
|
||||
entity.className + (entity.isDownlaod ? ProxyConstance.DOWNLOAD_PROXY_CLASS_SUFFIX
|
||||
: ProxyConstance.UPLOAD_PROXY_CLASS_SUFFIX))
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.FINAL);
|
||||
|
||||
//添加被代理的类的字段
|
||||
ClassName obj = ClassName.get(entity.packageName, entity.className);
|
||||
FieldSpec observerField = FieldSpec.builder(obj, "obj").addModifiers(Modifier.PRIVATE).build();
|
||||
builder.addField(observerField);
|
||||
|
||||
//添加注解方法
|
||||
for (Class<? extends Annotation> annotation : entity.methods.keySet()) {
|
||||
MethodSpec method =
|
||||
createProxyMethod(entity.isDownlaod, annotation, entity.methods.get(annotation));
|
||||
builder.addMethod(method);
|
||||
}
|
||||
|
||||
//添加设置代理的类
|
||||
ParameterSpec parameterSpec =
|
||||
ParameterSpec.builder(obj, "obj").addModifiers(Modifier.FINAL).build();
|
||||
MethodSpec listener = MethodSpec.methodBuilder(ProxyConstance.SET_LISTENER)
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.returns(void.class)
|
||||
.addParameter(parameterSpec)
|
||||
.addCode("this.obj = obj;\n")
|
||||
.build();
|
||||
builder.addJavadoc("该文件为Aria自动生成的代理文件,请不要修改该文件的任何代码!\n");
|
||||
|
||||
//创建父类参数
|
||||
ClassName superClass = ClassName.get("com.arialyy.aria.core.scheduler", "AbsSchedulerListener");
|
||||
//创建泛型
|
||||
ClassName typeVariableName = ClassName.get(
|
||||
entity.isDownlaod ? "com.arialyy.aria.core.download" : "com.arialyy.aria.core.upload",
|
||||
entity.isDownlaod ? "DownloadTask" : "UploadTask");
|
||||
builder.superclass(ParameterizedTypeName.get(superClass, typeVariableName));
|
||||
builder.addMethod(listener);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
void clean() {
|
||||
mMethods.clear();
|
||||
}
|
||||
@ -74,15 +226,21 @@ class ElementHandle {
|
||||
ElementKind kind = element.getKind();
|
||||
if (kind == ElementKind.METHOD) {
|
||||
ExecutableElement method = (ExecutableElement) element;
|
||||
TypeElement classElement = (TypeElement) method.getEnclosingElement();
|
||||
PackageElement packageElement = mElementUtil.getPackageOf(classElement);
|
||||
checkDownloadMethod(isDownload, method);
|
||||
String methodName = method.getSimpleName().toString();
|
||||
String className = method.getEnclosingElement().toString();
|
||||
Set<String> methods = mMethods.get(className);
|
||||
if (methods == null) {
|
||||
methods = new HashSet<>();
|
||||
mMethods.put(className, methods);
|
||||
String className = method.getEnclosingElement().toString(); //全类名
|
||||
ProxyEntity proxyEntity = mMethods.get(className);
|
||||
if (proxyEntity == null) {
|
||||
proxyEntity = new ProxyEntity();
|
||||
proxyEntity.isDownlaod = isDownload;
|
||||
//proxyEntity.packageName = classElement.getQualifiedName().toString();
|
||||
proxyEntity.packageName = packageElement.getQualifiedName().toString();
|
||||
proxyEntity.className = classElement.getSimpleName().toString();
|
||||
mMethods.put(className, proxyEntity);
|
||||
}
|
||||
methods.add(methodName);
|
||||
proxyEntity.methods.put(annotationClazz, methodName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* 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.arialyy.compiler;
|
||||
|
||||
import javax.annotation.processing.Messager;
|
||||
@ -8,7 +23,7 @@ import javax.tools.Diagnostic;
|
||||
* Created by Aria.Lao on 2017/6/6.
|
||||
*/
|
||||
|
||||
public class PrintLog {
|
||||
class PrintLog {
|
||||
|
||||
private volatile static PrintLog INSTANCE = null;
|
||||
private Messager mMessager;
|
||||
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* 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.arialyy.compiler;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2017/6/7.
|
||||
*/
|
||||
|
||||
public interface ProxyConstance {
|
||||
/**
|
||||
* 设置观察者的方法
|
||||
*/
|
||||
String SET_LISTENER = "setListener";
|
||||
|
||||
/**
|
||||
* 下载的动态生成的代理类后缀
|
||||
*/
|
||||
String DOWNLOAD_PROXY_CLASS_SUFFIX = "$$DownloadListenerProxy";
|
||||
|
||||
/**
|
||||
* 上传的动态生成的代理类后缀
|
||||
*/
|
||||
String UPLOAD_PROXY_CLASS_SUFFIX = "$$UploadListenerProxy";
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* 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.arialyy.compiler;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by Aria.Lao on 2017/6/7.
|
||||
*/
|
||||
|
||||
class ProxyEntity {
|
||||
public String packageName;
|
||||
public String className;
|
||||
public boolean isDownlaod = true;
|
||||
|
||||
public Map<Class<? extends Annotation>, String> methods = new HashMap<>();
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
//package com.arialyy.compiler;
|
||||
//
|
||||
///**
|
||||
// * Created by AriaL on 2017/6/6.
|
||||
// */
|
||||
//
|
||||
//public class test {
|
||||
// Object obj;
|
||||
//
|
||||
// public void setObj(Object obj){
|
||||
// this.obj = obj;
|
||||
// }
|
||||
//
|
||||
// public void onPre(DownloadTask task){
|
||||
// obj.method(task);
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//}
|
Reference in New Issue
Block a user