add component-support code
This commit is contained in:
@@ -29,7 +29,7 @@ dependencies {
|
||||
|
||||
implementation component(':library')
|
||||
implementation component(':librarykotlin')
|
||||
implementation project(':core')
|
||||
implementation project(':component-core')
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
apply plugin: 'com.android.library'
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "29.0.1"
|
||||
1
component-support-core/.gitignore
vendored
Normal file
1
component-support-core/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
33
component-support-core/build.gradle
Normal file
33
component-support-core/build.gradle
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "29.0.1"
|
||||
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.0.2'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
}
|
||||
21
component-support-core/proguard-rules.pro
vendored
Normal file
21
component-support-core/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.plugin.component.support;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
assertEquals("com.plugin.component.support.test", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
2
component-support-core/src/main/AndroidManifest.xml
Normal file
2
component-support-core/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,2 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.plugin.component.support" />
|
||||
3
component-support-core/src/main/res/values/strings.xml
Normal file
3
component-support-core/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">support-code</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.plugin.component.support;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
component-support-plugin/build/libs/component-support-1.0.0.jar
Normal file
BIN
component-support-plugin/build/libs/component-support-1.0.0.jar
Normal file
Binary file not shown.
@@ -0,0 +1 @@
|
||||
implementation-class=com.plugin.component.ComponentPlugin
|
||||
2
component-support-plugin/build/tmp/jar/MANIFEST.MF
Normal file
2
component-support-plugin/build/tmp/jar/MANIFEST.MF
Normal file
@@ -0,0 +1,2 @@
|
||||
Manifest-Version: 1.0
|
||||
|
||||
@@ -4,9 +4,6 @@ import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
|
||||
/**
|
||||
* ./gradlew --no-daemon ComponentPlugin -Dorg.gradle.debug=true
|
||||
* ./gradlew --no-daemon [clean, :app:generateDebugSources, :library:generateDebugSources, :module_lib:generateDebugSources] -Dorg.gradle.debug=true
|
||||
* ./gradlew --no-daemon :app:assemble -Dorg.gradle.debug=true
|
||||
* 组件插件入口
|
||||
* created by yummylau 2019/08/09
|
||||
*/
|
||||
@@ -15,10 +12,8 @@ class ComponentPlugin implements Plugin<Project> {
|
||||
@Override
|
||||
void apply(Project project) {
|
||||
boolean isRoot = project == project.rootProject
|
||||
if (isRoot) {
|
||||
handleRootProject(project)
|
||||
} else {
|
||||
handleProject(project)
|
||||
if (!isRoot) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.plugin.component.support
|
||||
|
||||
/**
|
||||
* logger 管理
|
||||
* created by yummylau 2019/08/09
|
||||
*/
|
||||
class Logger {
|
||||
|
||||
static void buildOutput(String log) {
|
||||
System.out.println(" " + log)
|
||||
}
|
||||
|
||||
static void buildOutput(Object start, Object end) {
|
||||
System.out.println(" " + start + " = " + end)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.plugin.component.anno;
|
||||
package com.plugin.component.support.anno;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.plugin.component.extension
|
||||
package com.plugin.component.support.extension
|
||||
/**
|
||||
* 插件配置
|
||||
* created by yummylau 2019/08/09
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.plugin.component.support.transform
|
||||
|
||||
import com.plugin.component.support.anno.MethodCost
|
||||
import org.objectweb.asm.*
|
||||
import org.objectweb.asm.commons.AdviceAdapter
|
||||
|
||||
class MethodCostAdapter extends ClassVisitor {
|
||||
|
||||
private static final String sCostCachePath = "com/plugin/component/CostCache"
|
||||
private String className
|
||||
|
||||
MethodCostAdapter(ClassVisitor classVisitor) {
|
||||
super(Opcodes.ASM7, classVisitor)
|
||||
}
|
||||
|
||||
@Override
|
||||
void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
||||
className = name
|
||||
super.visit(version, access, name, signature, superName, interfaces)
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
MethodVisitor visitMethod(int access, String name, String methodDescriptor, String signature, String[] exceptions) {
|
||||
MethodVisitor mv = super.visitMethod(access, name, methodDescriptor, signature, exceptions)
|
||||
mv = new AdviceAdapter(Opcodes.ASM7, mv, access, name, methodDescriptor) {
|
||||
|
||||
private boolean injectMethodCostCode = false
|
||||
private String methodName
|
||||
|
||||
@Override
|
||||
AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
|
||||
if (Type.getDescriptor(MethodCost.class) == descriptor) {
|
||||
ScanRuntime.addCostMethod(className, name, methodDescriptor)
|
||||
}
|
||||
return super.visitAnnotation(descriptor, visible)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMethodEnter() {
|
||||
injectMethodCostCode = ScanRuntime.isCostMethod(className, name, descriptor)
|
||||
methodName = className + "#" + name
|
||||
|
||||
if (injectMethodCostCode) {
|
||||
mv.visitLdcInsn(methodName)
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", "currentTimeMillis", "()J", false)
|
||||
mv.visitMethodInsn(INVOKESTATIC, sCostCachePath, "start",
|
||||
"(Ljava/lang/String;J)V", false)
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMethodExit(int opcode) {
|
||||
if (injectMethodCostCode) {
|
||||
mv.visitLdcInsn(methodName)
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", "currentTimeMillis", "()J", false)
|
||||
mv.visitMethodInsn(INVOKESTATIC, sCostCachePath, "end",
|
||||
"(Ljava/lang/String;J)V", false)
|
||||
|
||||
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;")
|
||||
mv.visitLdcInsn(methodName)
|
||||
mv.visitMethodInsn(INVOKESTATIC, sCostCachePath, "cost",
|
||||
"(Ljava/lang/String;)Ljava/lang/String;", false)
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
|
||||
"(Ljava/lang/String;)V", false)
|
||||
}
|
||||
}
|
||||
}
|
||||
return mv
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
package com.plugin.component.transform
|
||||
package com.plugin.component.support.transform
|
||||
|
||||
import com.android.build.api.transform.Context
|
||||
import com.android.build.api.transform.TransformException
|
||||
import com.android.build.api.transform.TransformInput
|
||||
import com.android.build.api.transform.TransformOutputProvider
|
||||
import com.plugin.component.Logger
|
||||
import com.plugin.component.transform.info.ScanRuntime
|
||||
import com.quinn.hunter.transform.HunterTransform
|
||||
import com.quinn.hunter.transform.RunVariant
|
||||
import org.gradle.api.Project
|
||||
@@ -14,15 +12,13 @@ class ScanCodeTransform extends HunterTransform {
|
||||
|
||||
ScanCodeTransform(Project project) {
|
||||
super(project)
|
||||
this.bytecodeWeaver = new ScanCodeWeaver()
|
||||
this.bytecodeWeaver = new MethodCostWeaver()
|
||||
}
|
||||
|
||||
@Override
|
||||
void transform(Context context, Collection<TransformInput> inputs, Collection<TransformInput> referencedInputs, TransformOutputProvider outputProvider, boolean isIncremental) throws IOException, TransformException, InterruptedException {
|
||||
long startTime = System.currentTimeMillis()
|
||||
super.transform(context, inputs, referencedInputs, outputProvider, isIncremental)
|
||||
ScanRuntime.logScanInfo()
|
||||
ScanRuntime.buildComponentSdkInfo()
|
||||
Logger.buildOutput("scan code cost : " + (System.currentTimeMillis() - startTime) + "ms")
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package com.plugin.component.transform
|
||||
package com.plugin.component.support.transform
|
||||
|
||||
import com.quinn.hunter.transform.asm.BaseWeaver
|
||||
import org.objectweb.asm.ClassVisitor
|
||||
import org.objectweb.asm.ClassWriter
|
||||
|
||||
class ScanCodeWeaver extends BaseWeaver {
|
||||
class MethodCostWeaver extends BaseWeaver {
|
||||
|
||||
@Override
|
||||
protected ClassVisitor wrapClassWriter(ClassWriter classWriter) {
|
||||
return new InjectCodeAdapter(classWriter)
|
||||
return new MethodCostAdapter(classWriter)
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
package com.plugin.component.transform
|
||||
|
||||
import com.plugin.component.anno.AutoInjectComponent
|
||||
import com.plugin.component.anno.AutoInjectImpl
|
||||
import com.plugin.component.anno.MethodCost
|
||||
import com.plugin.component.transform.info.ScanComponentInfo
|
||||
import com.plugin.component.transform.info.ScanRuntime
|
||||
import com.plugin.component.transform.info.ScanSdkInfo
|
||||
import org.objectweb.asm.*
|
||||
import org.objectweb.asm.commons.AdviceAdapter
|
||||
|
||||
class ScanCodeAdapter extends ClassVisitor {
|
||||
|
||||
private String className
|
||||
|
||||
ScanCodeAdapter(ClassVisitor classVisitor) {
|
||||
super(Opcodes.ASM7, classVisitor)
|
||||
}
|
||||
|
||||
@Override
|
||||
void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
||||
className = name
|
||||
super.visit(version, access, name, signature, superName, interfaces)
|
||||
}
|
||||
|
||||
@Override
|
||||
AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
|
||||
AnnotationVisitor annotationVisitor = super.visitAnnotation(descriptor, visible)
|
||||
ScanComponentInfo scanComponentInfo = null
|
||||
ScanSdkInfo scanSdkInfo = null
|
||||
return new AnnotationVisitor(Opcodes.ASM7, annotationVisitor) {
|
||||
|
||||
@Override
|
||||
AnnotationVisitor visitArray(String arrayName) {
|
||||
|
||||
return new AnnotationVisitor(Opcodes.ASM7, super.visitArray(arrayName)) {
|
||||
@Override
|
||||
void visit(String name, Object value) {
|
||||
if (Type.getDescriptor(AutoInjectComponent.class) == descriptor) {
|
||||
if (arrayName != null && arrayName == "impl") {
|
||||
if (value != null) {
|
||||
if (scanComponentInfo == null) {
|
||||
scanComponentInfo = new ScanComponentInfo(className)
|
||||
}
|
||||
scanComponentInfo.impl.add((String) value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Type.getDescriptor(AutoInjectImpl.class) == descriptor) {
|
||||
if (arrayName != null && arrayName == "sdk") {
|
||||
if (value != null) {
|
||||
if (scanSdkInfo == null) {
|
||||
scanSdkInfo = new ScanSdkInfo(className)
|
||||
}
|
||||
scanSdkInfo.sdk.add((String) value)
|
||||
}
|
||||
}
|
||||
}
|
||||
super.visit(name, value)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void visitEnd() {
|
||||
if (scanComponentInfo != null) {
|
||||
ScanRuntime.addComponentInfo(scanComponentInfo)
|
||||
scanComponentInfo = null
|
||||
}
|
||||
if (scanSdkInfo != null) {
|
||||
ScanRuntime.addSdkInfo(scanSdkInfo)
|
||||
scanSdkInfo = null
|
||||
}
|
||||
super.visitEnd()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
MethodVisitor visitMethod(int access, String name, String methodDescriptor, String signature, String[] exceptions) {
|
||||
MethodVisitor mv = super.visitMethod(access, name, methodDescriptor, signature, exceptions)
|
||||
mv = new AdviceAdapter(Opcodes.ASM7, mv, access, name, methodDescriptor) {
|
||||
@Override
|
||||
AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
|
||||
if (Type.getDescriptor(MethodCost.class) == descriptor) {
|
||||
ScanRuntime.addCostMethod(className, name, methodDescriptor)
|
||||
}
|
||||
return super.visitAnnotation(descriptor, visible)
|
||||
}
|
||||
}
|
||||
return mv
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
apply plugin: 'com.android.library'
|
||||
android {
|
||||
|
||||
compileSdkVersion 29
|
||||
@@ -29,7 +28,7 @@ dependencies {
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
implementation project(':core')
|
||||
implementation project(':component-core')
|
||||
implementation component(':librarykotlin')
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
@@ -33,7 +32,7 @@ dependencies {
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
implementation project(':core')
|
||||
implementation project(':component-core')
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
}
|
||||
repositories {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
include ':app', ':library', ':core', ':librarykotlin'
|
||||
include ':app', ':library', ':component-core', ':librarykotlin', ':component-support-core'
|
||||
|
||||
|
||||
//调试插件使用
|
||||
includeBuild './component-plugin'
|
||||
|
||||
Reference in New Issue
Block a user