Skip to content

Commit

Permalink
Compile scan version1.8:
Browse files Browse the repository at this point in the history
1. update the library.
  • Loading branch information
JoelZhu committed Apr 8, 2023
1 parent d961d1d commit ccaf924
Show file tree
Hide file tree
Showing 18 changed files with 285 additions and 161 deletions.
148 changes: 69 additions & 79 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,107 +8,97 @@ Classes scanner for Android applications, which supply interfaces to get annotat
![last commit](https://img.shields.io/github/last-commit/JoelZhu/CompileScanner?color=pink&label=commited&style=for-the-badge)

### ✨ Overall
<a href="#%EF%B8%8F-deploy">Deploy</a> | <a href="#%EF%B8%8F-usage">Usage</a> | Troubles(To do)
<a href="#%EF%B8%8F-deploy">Deploy</a> | <a href="#%EF%B8%8F-usage">Usage</a> | <a href="#-troubles">Troubles</a>

### 🛠️ Deploy
Deploy the library use the dependencies below:
```
To deploy the library as two steps:
1. declare in project's build.gradle as below:
```groovy
dependencies {
implementation "io.github.joelzhu:scanner-runtime:[RELEASED_VERSION]"
annotationProcessor "io.github.joelzhu:scanner-compile:[RELEASED_VERSION]"
classpath "io.github.joelzhu:scanner-plugin:[RELEASED_VERSION]"
}
```
if you are using kotlin, please replace ```annotationProcessor``` with ```kapt```, and add plugin together, as below:
```
2. declare in application's build.gradle as below:
```groovy
plugins {
...
id 'kotlin-kapt'
id 'com.joelzhu.scanner'
}
dependencies {
...
kapt "io.github.joelzhu:scanner-compile:[RELEASED_VERSION]"
implementation "io.github.joelzhu:scanner-runtime:[RELEASED_VERSION]"
}
```
There's no obverse differences between using Java and Kotlin.

**Important!!
Only implement is not enough, please read the content below, there are some different compile options to add in different situations.**

Quick guide: <a href="#only-an-application-module">Only an application module</a> | <a href="#implemented-library-modules-with-compilescan">Implemented library module(s) with ```@CompileScan```</a> | <a href="#description-of-compile-options">Description of compile options</a>
### 🗒️ Usage
Quick guide: <a href="#simple-usage">Simple usage</a> | <a href="#advanced-usage-default">Advanced usage: default</a> | <a href="#advanced-usage-priority">Advanced usage: priority</a> | <a href="#description-of-fields">Description of fields</a>

#### Only an application module
If you are only an application module exists, without any library modules to implement, write down the code into application module's ```build.gradle```
```
android {
...
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = [
appModule: 'true'
]
}
}
}
}
##### Simple usage
For simple usage, coding as below:
```java
@CompileScan
public class ExampleClass implements IExample {}
```
And you will got the classes or array of instances when you call ```Scanner```'s public method.

#### Implemented library module(s) with ```@CompileScan```
##### Application module without ```@CompileScan``` in it
If you are using Android library module(s) in your project, you should specify it in compile options, which also defined into application module's ```build.gradle```
```
android {
...
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = [
appModule : 'true',
isMultiModule : 'true'
]
}
}
##### Advanced usage: default
You can use the ```Scanner``` as a compilation Proxy. For example, you have a class A as below:
```java
@CompileScan(tag = "ProxySample", isDefault = true)
public class ProxyA implements IProxy {
@Override
public String printName() {
return "I'm A.";
}
}
```
##### Application module with ```@CompileScan``` in it
And if the application module still have annotation: ```@CompileScan```, you should add option ```withAnnotation: 'true'``` into ```build.gradle``` additional, for example:
```
android {
...
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = [
appModule : 'true',
isMultiModule : 'true',
withAnnotation: 'true'
]
}
}
and you have another class B as below:
```java
@CompileScan(tag = "ProxySample")
public class ProxyB implements IProxy {
@Override
public String printName() {
return "I'm B.";
}
}
```
#### Description of compile options
|Compile Options|Description|
|----|----|
|appModule|Indicate whether current module is application module|
|isMultiModule|Indicate whether implemented library module has ```@CompileScan```|
|withAnnotation|Indicate whether application module has ```@CompileScan```|
### 🗒️ Usage
For simple usage, coding as below:
If you call the method like: ```Scanner.getAnnotatedInstances(new Options.Builder("ProxySample").create(), IProxy.class);```, you will got the array of ```Class``` which has ```IProxy.class``` in it.
And you call ```IProxy```'s ```printName()```, you will got the string: ```I'm B.```.
This may help you implement pattern - Proxy easily.

##### Advanced usage: priority
You can set priority of the classes with the same tag. For example:
If class ```First``` has the higher priority of the class ```Second```, you can annotated them as below:
```java
@CompileScan(priority = 1)
public class First {}
```
@CompileScan
public class ExampleClass implements IExample {
...
}
```java
@CompileScan(priority = 2)
public class Second {}
```
Then, you can get all of those annotated classes by: ```Scanner.getAnnotatedInstances(IExample.class)```, and you will get an array of instances typed by```IExample.class```
And you will got the array, which put the ```First``` above the ```Second```.

##### Description of fields
| Fields | Description |
|------------|---------------------------------------------------------|
| tag | Mark the annotated classes as different groups |
| isDefault | Differ the classes with default one or not |
| priority | Indicate the priority of each classes with the same tag |

Some advanced usage below:
* You can add a string to mark them with different tags, such as: ```@CompileScan(tag = "Class1")```. Then, through method: ```Scanner.getAnnotatedInstances("Class1", XXX.class)``` to acquire those annotated classes' instances
* You can specify those classes' priority, like: ```@CompileScan(priority = 2)```. Then, this class will be arranged at the second place if ```priority = 1``` exists, if not, this class will still placed at the first place
> For more examples, see the code in the project. [Java Example](https://github.com/JoelZhu/CompileScanner/tree/main/app_sample_java) | [Kotlin Example](https://github.com/JoelZhu/CompileScanner/tree/main/app_sample_kotlin) | [Multi Modules Usage Example](https://github.com/JoelZhu/CompileScanner/tree/main/app_sample_multimodule_app)
### ❗ Troubles
If you got compile exceptions, add the options below in application's build.gradle:
```groovy
android {
}
Scanner {
enableLog = true
}
dependencies {
}
```
and copy the compile stack trace into an new issue, assign to me, i will try my best to resolve the problem as fast as you wish.
4 changes: 4 additions & 0 deletions app_sample_java/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ android {
}
}

Scanner {
enableLog = true
}

dependencies {
implementation "io.github.joelzhu:scanner-runtime:${VERSION_NAME}"
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ private String printManDoing() {
}
return stringBuilder.toString();
}

private String printWomanDoing() {
final StringBuilder stringBuilder = new StringBuilder();
final Options options = new Options.Builder(Constants.TAG_WOMAN).create();
Expand Down
4 changes: 4 additions & 0 deletions app_sample_kotlin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ android {
}
}

Scanner {
enableLog = true
}

dependencies {
implementation "io.github.joelzhu:scanner-runtime:${VERSION_NAME}"
}
4 changes: 4 additions & 0 deletions app_sample_multimodule_app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ android {
}
}

Scanner {
enableLog = true
}

dependencies {
implementation project(':app_sample_multimodule_lib0')
implementation project(':app_sample_multimodule_lib1')
Expand Down
13 changes: 7 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ allprojects {
repositories {
google()
mavenCentral()
maven{ url = "https://maven.aliyun.com/repository/public/" }
maven{ url = "https://maven.aliyun.com/repository/central" }
maven { url = "https://maven.aliyun.com/repository/public/" }
maven { url = "https://maven.aliyun.com/repository/central" }
mavenLocal()
}

Expand All @@ -14,7 +14,7 @@ allprojects {
}
}

// 增加编译信息
// For more compile information
// gradle.projectsEvaluated {
// tasks.withType(JavaCompile) {
// options.compilerArgs << "-Xlint" << "-verbose" << "-XprintRounds" << "-XprintProcessorInfo" << "-Xmaxerrs" << "100000"
Expand All @@ -41,8 +41,8 @@ buildscript {
repositories {
google()
mavenCentral()
maven{ url = "https://maven.aliyun.com/repository/public/" }
maven{ url = "https://maven.aliyun.com/repository/central" }
maven { url = "https://maven.aliyun.com/repository/public/" }
maven { url = "https://maven.aliyun.com/repository/central" }
mavenLocal()
}
dependencies {
Expand All @@ -51,7 +51,8 @@ buildscript {
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10"
// AAR发布插件

// Publish library&plugin
classpath "com.vanniktech:gradle-maven-publish-plugin:0.18.0"

// Compile scanner
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ package com.joelzhu.lib.scanner.annotation
* The annotation which declare the class should been scanned at the progress of compiling.
*
* @param tag TAG of annotated classes, accessor will classified by this TAG.
* @param isDefault Mark the current one is default.
* @param isDefault Mark the current one is default. The difference between true and false is:
* If you have two classes with the same tag, one is default, the other is not,
* you will only got the non-default one.
* @param priority The priority of annotated classes, index of each class will sorted by the
* number which defined here. The priority should defined from 0 to positive,
* for example, 0 will stay above 1. Default priority is the lowest.
* number which defined here. The priority should defined from 0 to positive,
* for example, 0 will stay above 1. Default priority is the lowest.
*
* @author JoelZhu
* @since 2023-01-17
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.joelzhu.lib.scanner.annotation
/**
* [Description here].
*
* @author zhuqian
* @author JoelZhu
* @since 2023-04-07
*/
object ImplConstants {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.joelzhu.lib.scanner.plugin

import com.android.build.gradle.AppExtension
import com.joelzhu.lib.scanner.plugin.core.ScannerTransform
import com.joelzhu.lib.scanner.plugin.extension.ExtensionConfig
import com.joelzhu.lib.scanner.plugin.util.LogUtil
import org.gradle.api.Plugin
import org.gradle.api.Project

Expand All @@ -13,7 +15,20 @@ import org.gradle.api.Project
*/
class ScannerPlugin : Plugin<Project> {
override fun apply(project: Project) {
val extension = project.extensions.findByType(AppExtension::class.java)
extension?.registerTransform(ScannerTransform())
val container = project.extensions
container.create("Scanner", ExtensionConfig::class.java)
container.findByType(AppExtension::class.java)?.registerTransform(ScannerTransform())

project.afterEvaluate {
val extension = project.extensions.findByType(ExtensionConfig::class.java)
val isEnableLogPrint = extension != null && extension.enableLog
val logPrintResultContent = if (isEnableLogPrint) {
"enabled."
} else {
"disabled."
}
LogUtil.adjustLogPrintPrivacy(isEnableLogPrint)
println("Scanner's log print $logPrintResultContent.")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import org.apache.commons.codec.digest.DigestUtils
import java.io.File

/**
* [Description here].
* Transform of scanner.
* To scan classes which annotated with the annotation: [CompileScan][com.joelzhu.lib.scanner.annotation.CompileScan]
*
* @author JoelZhu
* @since 2023-03-30
Expand Down Expand Up @@ -50,6 +51,7 @@ class ScannerTransform : Transform() {

TransformHandler.onCompileStarted()

// Find out how many directory inputs with classes in it.
LogUtil.printEmptyLine()
LogUtil.printLog("To find all the directoryInputs which with class(es) in it.")
scanDirInputWhichWithClasses(invocation)
Expand Down Expand Up @@ -99,10 +101,10 @@ class ScannerTransform : Transform() {

var logContent = "List of dirInput(s) with class(es) in it: "
TransformHandler.getDirectoryInputsWithClasses().forEachIndexed { index, dirInputName ->
if (index == 0) {
logContent += dirInputName
logContent += if (index == 0) {
dirInputName
} else {
logContent += ", $dirInputName"
", $dirInputName"
}
}
LogUtil.printLog(logContent)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ object TransformHandler {

fun scanDirectoryInputWhichWithClasses(dirInput: DirectoryInput, dirInputName: String) {
FileUtils.getAllFiles(dirInput.file).forEach { file ->
if (!file.name.endsWith(".class")) {
return
if (isDirInputWithClasses(dirInputName)) {
return@scanDirectoryInputWhichWithClasses
}

if (!file.exists()) {
return
if (!file.name.endsWith(".class") || !file.exists()) {
return@forEach
}

val inputStream = file.inputStream()
Expand All @@ -91,10 +91,10 @@ object TransformHandler {
}

fun updateDirectoryWithClasses(dirInputName: String) {
if (dirWithClass.contains(dirInputName)) {
if (isDirInputWithClasses(dirInputName)) {
return
}

LogUtil.printLog("Found class(es) in dirInput: $dirInputName.")
dirWithClass.add(dirInputName)
}
Expand All @@ -114,4 +114,8 @@ object TransformHandler {
val visitor = ClassScanVisitor(writer, fileAbsPath)
reader.accept(visitor, ClassReader.EXPAND_FRAMES)
}

private fun isDirInputWithClasses(dirInputName: String): Boolean {
return dirWithClass.contains(dirInputName)
}
}

0 comments on commit ccaf924

Please sign in to comment.