Skip to content

Commit

Permalink
Use Transform API for weaving instead of hooking into tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
Can Elmas authored and Can Elmas committed Sep 3, 2017
1 parent 000bde2 commit 97ee495
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 54 deletions.
69 changes: 15 additions & 54 deletions let-plugin/src/main/groovy/com/canelmas/let/LetPlugin.groovy
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/*
* Copyright (C) 2015 Can Elmas
* Copyright (C) 2017 Can Elmas
*
* 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
* 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,
Expand All @@ -18,71 +18,32 @@ package com.canelmas.let

import com.android.build.gradle.AppPlugin
import com.android.build.gradle.LibraryPlugin
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.compile.JavaCompile

class LetPlugin implements Plugin<Project> {

@Override void apply(Project project) {
def hasApp = project.plugins.withType(AppPlugin)
def hasLib = project.plugins.withType(LibraryPlugin)
if (!hasApp && !hasLib) {
throw new IllegalStateException("'android' or 'android-library' plugin required.")
}
@Override
void apply(Project project) {

final def log = project.logger
final def variants
if (hasApp) {
variants = project.android.applicationVariants
} else {
variants = project.android.libraryVariants
}
makeSureProjectIsAndroidAppOrLib(project)

project.android.registerTransform(new LetTransform(project))

project.dependencies {
implementation 'org.aspectj:aspectjrt:1.8.10'
implementation 'org.aspectj:aspectjrt:1.8.9'
implementation 'com.canelmas.let:let-runtime:1.0.0-beta1'
implementation 'com.canelmas.let:let-annotations:1.0.0-beta1'
}
}

variants.all { variant ->
JavaCompile javaCompile = variant.javaCompile
javaCompile.doLast {
String[] args = [
"-showWeaveInfo",
"-1.5",
"-inpath", javaCompile.destinationDir.toString(),
"-aspectpath", javaCompile.classpath.asPath,
"-d", javaCompile.destinationDir.toString(),
"-classpath", javaCompile.classpath.asPath,
"-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)
]
log.debug "ajc args: " + Arrays.toString(args)
private void makeSureProjectIsAndroidAppOrLib(Project project) {
def hasApp = project.plugins.withType(AppPlugin)
def hasLib = project.plugins.withType(LibraryPlugin)

MessageHandler handler = new MessageHandler(true);
new Main().run(args, handler);
for (IMessage message : handler.getMessages(null, true)) {
switch (message.getKind()) {
case IMessage.ABORT:
case IMessage.ERROR:
case IMessage.FAIL:
log.error message.message, message.thrown
break;
case IMessage.WARNING:
log.warn message.message, message.thrown
break;
case IMessage.INFO:
log.info message.message, message.thrown
break;
case IMessage.DEBUG:
log.debug message.message, message.thrown
break;
}
}
}
if (!hasApp && !hasLib) {
throw new IllegalStateException("'android' or 'android-library' plugin required.")
}
}

}
150 changes: 150 additions & 0 deletions let-plugin/src/main/groovy/com/canelmas/let/LetTransform.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/*
* Copyright (C) 2017 Can Elmas
*
* 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.canelmas.let

import com.android.annotations.NonNull
import com.android.build.api.transform.*
import com.google.common.base.Joiner
import com.google.common.base.Strings
import com.google.common.collect.Lists
import com.google.common.collect.Sets
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.logging.Logger

class LetTransform extends Transform {

private Project project

LetTransform(Project project) {
this.project = project
}

@Override
void transform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException {

List<File> files = Lists.newArrayList()
List<File> classpathFiles = Lists.newArrayList()
Logger logger = project.logger

TransformOutputProvider outputProvider = transformInvocation.getOutputProvider()

// clean
outputProvider.deleteAll()

// Referenced Inputs to classpath
for (TransformInput input : transformInvocation.getReferencedInputs()) {
input.directoryInputs.each {
classpathFiles.add(it.file)
}

input.jarInputs.each {
classpathFiles.add(it.file)
}
}

// Scope inputs
for (TransformInput input : transformInvocation.getInputs()) {

for (DirectoryInput folder : input.directoryInputs) {
files.add(folder.file)
}

for (JarInput jar : input.jarInputs) {
files.add(jar.file)
}
}

// Evaluate class paths
final String inpath = Joiner.on(File.pathSeparator).join(files)
final String classpath = Joiner.on(File.pathSeparator).join(
classpathFiles.collect { it.absolutePath })
final String bootpath = Joiner.on(File.pathSeparator).join(project.android.bootClasspath)
final File output = outputProvider.getContentLocation("main", outputTypes, Sets.immutableEnumSet(QualifiedContent.Scope.PROJECT), Format.DIRECTORY)

// Weaving args
def args = [
"-source", "1.6",
"-target", "1.6",
"-showWeaveInfo",
"-inpath", inpath,
"-d", output.absolutePath,
"-bootclasspath", bootpath]

// Append classpath argument if any
if (!Strings.isNullOrEmpty(classpath)) {
args << '-classpath'
args << classpath
}

// run aspectj
MessageHandler handler = new MessageHandler(true)
new Main().run(args as String[], handler)

for (IMessage message : handler.getMessages(null, true)) {

if (IMessage.ERROR.isSameOrLessThan(message.kind)) {
logger.error(message.message, message.thrown)
throw new GradleException(message.message, message.thrown)
} else if (IMessage.WARNING.isSameOrLessThan(message.kind)) {
logger.warn message.message
} else if (IMessage.DEBUG.isSameOrLessThan(message.kind)) {
logger.info message.message
} else {
logger.debug message.message
}
}

}

@NonNull
@Override
String getName() {
"let"
}

@NonNull
@Override
Set<QualifiedContent.ContentType> getInputTypes() {
return Sets.immutableEnumSet(QualifiedContent.DefaultContentType.CLASSES)
}

@NonNull
@Override
Set<QualifiedContent.Scope> getScopes() {
return Sets.immutableEnumSet(QualifiedContent.Scope.PROJECT,
QualifiedContent.Scope.EXTERNAL_LIBRARIES)
}

@Override
Set<QualifiedContent.Scope> getReferencedScopes() {
return Sets.immutableEnumSet(
QualifiedContent.Scope.SUB_PROJECTS,
QualifiedContent.Scope.EXTERNAL_LIBRARIES,
QualifiedContent.Scope.PROVIDED_ONLY
)
}

@Override
boolean isIncremental() {
false
}

}

0 comments on commit 97ee495

Please sign in to comment.