add component-support code

This commit is contained in:
yummylau
2019-08-27 21:28:51 +08:00
parent 9447b4c19f
commit 7f53a730f6
45 changed files with 208 additions and 121 deletions

View File

@@ -29,7 +29,7 @@ dependencies {
implementation component(':library')
implementation component(':librarykotlin')
implementation project(':core')
implementation project(':component-core')
}

View File

@@ -1,4 +1,3 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 29
buildToolsVersion "29.0.1"

1
component-support-core/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View 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'
}

View 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

View File

@@ -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());
}
}

View File

@@ -0,0 +1,2 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.plugin.component.support" />

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">support-code</string>
</resources>

View File

@@ -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);
}
}

View File

@@ -0,0 +1 @@
implementation-class=com.plugin.component.ComponentPlugin

View File

@@ -0,0 +1,2 @@
Manifest-Version: 1.0

View File

@@ -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) {
}
}
}

View File

@@ -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)
}
}

View File

@@ -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;

View File

@@ -1,4 +1,4 @@
package com.plugin.component.extension
package com.plugin.component.support.extension
/**
* 插件配置
* created by yummylau 2019/08/09

View File

@@ -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
}
}

View File

@@ -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")
}

View File

@@ -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)
}
}

View File

@@ -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
}
}

View File

@@ -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')
}

View File

@@ -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 {

View File

@@ -1,4 +1,5 @@
include ':app', ':library', ':core', ':librarykotlin'
include ':app', ':library', ':component-core', ':librarykotlin', ':component-support-core'
//调试插件使用
includeBuild './component-plugin'