Let's say that I wan to override (replace) the default setting for the packageBin task. So I naively wrote an AutoPlugin like this:
object TestPlugin extends AutoPlugin {
override def trigger = allRequirements
override val projectSettings: Seq[Def.Setting[_]] = Seq(
packageBin in Compile <<= (packageBin in Compile).map { a =>
println("project/compile::packageBin")
a
}
)
}
But this does not work (at least not with SBT 0.13.5 and 0.13.6-M1), my version of packageBin gets never called. If I put the the following line in my project's build.sbt file, then it works.
packageBin in Compile <<= (packageBin in Compile).map { a => println("project/compile::packageBin"); a }
Is it possible at all to achieve this from an AutoPlugin or a classical plugin, and if so how?
I found the solution to the problem here.
In order to make sure that the settings of the AutoPlugin are not overwritten by the default settings, the settings from the AutoPlugin must be applied after the default settings. The default settings are set by the AutoPlugins in package sbt.plugins (CorePlugin, IvyPlugin, JvmPlugin).
So all I had to do, is to make my AutoPlugin dependent on the JvmPlugin by adding the following override to my AutoPlugin:
override def requires: Plugins = JvmPlugin
The complete autoplugin with the overriden packageBin is as follows:
import sbt._
import Keys._
import plugins.JvmPlugin
object TestPlugin extends AutoPlugin {
override def requires = JvmPlugin
override def trigger = allRequirements
override val projectSettings: Seq[Def.Setting[_]] = Seq(
packageBin in Compile <<= (packageBin in Compile).map { a =>
println("project/compile::packageBin")
a
}
)
}
Just to complete the answer from #user1752169, here's a shorter (not necessarily simpler to comprehend) solution with the to-be-forgotten operator ~=:
import sbt._
import Keys._
import plugins.JvmPlugin
object TestPlugin extends AutoPlugin {
override def requires = JvmPlugin
override def trigger = allRequirements
override val projectSettings: Seq[Def.Setting[_]] = Seq(
packageBin in Compile ~= { a =>
println("project/compile::packageBin")
a
}
)
}
Or to have a side-effecting post-processing with andFinally:
import sbt._
import Keys._
import plugins.JvmPlugin
object TestPlugin extends AutoPlugin {
override def requires = JvmPlugin
override def trigger = allRequirements
override val projectSettings: Seq[Def.Setting[_]] = Seq(
packageBin in Compile <<= (packageBin in Compile) andFinally {
println("project/compile::packageBin")
}
)
}
As a nice addition, one may save the autoplugin code to project/src/main/scala in any project and gets the plugin activated without much work (and constantly updated when changed).
Related
I have a simplified test case where I'm calling createUserWithEmailAndPassword(...).await() from FirebaseAuth that leads to the exception
java.lang.IllegalStateException: This job has not completed yet
I'm using the InstantTaskExecutorRule but this doesn't help.
Here is my simplified test class:
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.google.firebase.auth.ktx.auth
import com.google.firebase.ktx.Firebase
import kotlinx.coroutines.tasks.await
import kotlinx.coroutines.test.runBlockingTest
import org.junit.Rule
import org.junit.Test
class FirebaseCoroutineTest {
#get:Rule
val instantTaskExecutorRule = InstantTaskExecutorRule()
val auth = Firebase.auth.apply {
this.useEmulator("10.0.2.2", 9099)
}
#Test
fun testCreateUser() = runBlockingTest {
auth.createUserWithEmailAndPassword("test#user.null", "testpwd").await()
}
}
What's the correct way to do this test.
using runBlocking instead of runBlockingTest solves the issue.
Building library module. And in the sample application which is using the library module it has
#GlideModule
class DPAppGlideModule : AppGlideModule() {
override fun isManifestParsingEnabled(): Boolean {
return false
}
}
and in the library module has:
#GlideModule
public final class LibGlideModule extends LibraryGlideModule {
}
and in the library module it is using the GlideApp the generated api
fun ImageView.loadImg(imageUrl: String) {
var requestOptions : RequestOptions = RequestOptions()
requestOptions.diskCacheStrategy(DiskCacheStrategy.ALL)
if (!TextUtils.isEmpty(imageUrl)) {
GlideApp.with(this.context)
.setDefaultRequestOptions(requestOptions)
.load(imageUrl)
.into(this)
}
}
But since this is the library module and cannot have decency on the application module, so it cannot compile
How to use the GlideApp generated api in the library module?
ref — https://bumptech.github.io/glide/doc/configuration.html
Just add
annotationProcessor com.github.bumptech.glide:compiler:4.8.0
dependency in your module gradle file. sync project then clean and rebuild it.
If your module using kotlin. change "annotationProcessor" to "kapt".
Be careful if you have others module dependency,make sure you use the right GlideApp Object. Maybe others module have it own GlideApp object
I'm defining my build/release process in build.sbt. I also have a project/Build.scala that has some definitions which are used in build.sbt. Doing this to keep build.sbt readable.
I'm trying to add a few new tasks to the releaseProcess. I'm defining these tasks in Build.scala as
object StartService {
val myNewTask = taskKey[Unit]("Execute a CLI command")
myNewTask := {
streams.value.log.info(s"Executing command")
s"cmd $arg1 $arg2" !
}
}
build.sbt has
releaseProcess := Seq[ReleaseStep](
...
releaseStepTask(StartService.myNewTask)
...
)
When executing release command I keep getting an exception that myNewTask is undefined. What is the right way to import tasks defined in Build.scala?
java.lang.RuntimeException: /:myNewTask is undefined.
at scala.sys.package$.error(package.scala:27)
at sbt.Extracted$$anonfun$getOrError$1.apply(Extracted.scala:94)
at sbt.Extracted$$anonfun$getOrError$1.apply(Extracted.scala:94)
at scala.Option.getOrElse(Option.scala:120)
You need to add the task definition to your project. Just by being in an object, that doesn't happen. The simplest way is to add the setting directly into build.sbt.
To automatically add it to several projects, you could define it as a plugin in your project directory:
object SbtScaryPlugin extends AutoPlugin {
override def trigger = allRequirements
override def requires = JvmPlugin
object autoImport {
val myNewTask = taskKey[Unit]("Execute a CLI command")
}
import autoImport._
override lazy val projectSettings = Seq(
myNewTask := {
streams.value.log.info(s"Executing command")
s"cmd $arg1 $arg2" !
}
)
}
I'm getting the following error:
ReferenceError: MyClass is not defined
in meteor 1.2 (actually just updated to 1.2.0.2) with a class defined in lib from a server file.
class MyClass {
// lots of OOP code here .....
}
Do you have to do something special for meteor to pick up the new ES2015 class stuff? Thanks!
You have to declare the class global, like
MyClass = class MyClass { /*...*/ };
Since Meteor wraps all your .js files in IIFOs
As of Meteor 1.3
You should declare your class in imports/.../myClass.js as follows:
export class MyClass {
/* ... */
}
And whereever you want to use it:
import {MyClass} from 'imports/.../myClass';
/* ... */
MyClass.something();
What I would like to do is a flex app, that uses fonts that are available in external swf.
What I have succeded so far is:
to create a AS class hat holds the embedded font:
package
{
import flash.display.Sprite;
public class _Arial extends Sprite
{
[Embed(source='C:/WINDOWS/Fonts/ARIAL.TTF', fontName='_Arial', unicodeRange='U+0020-U+002F,U+0030-U+0039,U+003A-U+0040,U+0041-U+005A,U+005B-U+0060,U+0061-U+007A,U+007B-U+007E')]
public static var _MyArial:Class;
}
}
compiled this into a swf with following command: mxmlc.exe -static-link-runtime-shared-libraries=true _Arial.as
When I try to load the font from my flex app, this fails with following error message:
ArgumentError: Error #1508: The value specified for argument font is invalid.
at flash.text::Font$/registerFont()
at valueObjects::FontLoader/fontLoaded()[C:\Documents and Settings\nutrina\Adobe Flash Builder 4\flex_pdf\src\valueObjects\FontLoader.as:33]
This is the code where I try to load the SWF file:
package
{
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.net.URLRequest;
import flash.text.*;
import mx.collections.ArrayCollection;
import mx.core.FontAsset;
public class FontLoader extends Sprite {
public function FontLoader(url:String) {
super();
loadFont(url);
}
private function loadFont(url:String):void {
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, fontLoaded);
loader.load(new URLRequest(url));
}
private function fontLoaded(event:Event):void {
var fontList:ArrayCollection = new ArrayCollection(Font.enumerateFonts(true));
var FontLibrary:Class = event.target.applicationDomain.getDefinition("_Arial") as Class;
trace("FontList: " + fontList)
trace("FontLibrary: " + FontLibrary)
trace("FontLibrary._Arial: " + FontLibrary._MyArial)
Font.registerFont(FontLibrary._MyArial);
fontList = new ArrayCollection(Font.enumerateFonts(true));
trace("Font list: " + fontList)
}
}
}
The font file is definitely not corrupt because if I put the _Arial class from the code above into the Flex application, the embedding works. So my guess is that probably I missed some compilation options?
I am using Adobe Flash Builder 4.
I would appreciate any help on this matter.
Thanks,
Gerald
Could be a problem with class name conflicts. I wrestled with an external font loading issue for hours. Turns out my font class was called "Main", and so was the application that was trying to load it. The font never got registered correctly.