gh-pages / com.nextfaze.devfun.function / DeveloperFunction

DeveloperFunction

@Target([AnnotationTarget.FUNCTION]) annotation class DeveloperFunction (source)

Functions/methods annotated with this will be shown on the Developer Menu (and other modules).

The function and its containing class can have any visibility:

At compile time, a FunctionDefinition will be generated referencing the function with this annotation.

At runtime the FunctionDefinition will be transformed to one or more FunctionItem via FunctionTransformer.

Properties

All properties are optional.

Name

When value is undefined, the name is derived from the function name split by camel case. (e.g. “myFunction” → “My Function”).

e.g. Change the name of a function to “A Slightly Better Name”:

class MyClass {
    @DeveloperFunction("A Slightly Better Name")
    fun A_STUPID_Name() {
        ...
    }
}

Category

The category property allows specifying and/or overloading the category details for this function (see DeveloperCategory).

e.g. Specify a different category:

class MyClass {
    @DeveloperFunction(category = DeveloperCategory("My Class (Animation Utils)"))
    fun startAnimation() = Unit // category="My Class (Animation Utils)"
}

Specify a group for a function:

class MyClass {
    @DeveloperFunction(category = DeveloperCategory(group = "Special Snow Flake"))
    fun someFunction() = Unit // category="My Class", group="Special Snow Flake"

    @DeveloperFunction
    fun anotherFunction() = Unit // category="My Class", group="Misc" (as one or more groups are present)
}

(todo: add “group” value to DeveloperFunction annotation?)

Requires API

When requiresApi is specified this function will only be visible/referenced if the device meets the requirements.

(todo: use/look for @RequiresApi instead/as well?)

e.g. Restrict M function:

class MyClass {
    // Any device below M will not see this function and DevFun wont invoke any transformers upon it
    @RequiresApi(Build.VERSION_CODES.M)
    @DeveloperFunction(requiresApi = Build.VERSION_CODES.M)
    fun startAnimation() {
        // doing something M related
    }
}

Transformer

The transformer tells DevFun how to generate one or more FunctionItem from this function’s FunctionDefinition.

The default transformer is SingleFunctionTransformer which effectively just wraps the FunctionDefinition to a FunctionItem (1:1).

Item lifecycle:

For an in-depth explanation on transformers see FunctionTransformer.

e.g. Provide a list of items to automatically fill in and log in as a test account:

class MyAuthenticateFragment {
    ...

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        signInButton.apply {
            setOnClickListener { attemptLogin() }
        }
    }

    @DeveloperFunction(transformer = SignInFunctionTransformer::class)
    private fun signInAs(email: String, password: String) {
        emailEditText.setText(email)
        passwordEditText.setText(password)
        attemptLogin()
    }
}

private class SignInFunctionTransformer : FunctionTransformer {
    private data class TestAccount(val email: String, val password: String) {
        val title = "Authenticate as $email" // this will be the name of the item - this is effectively @DeveloperFunction("Authenticate as $email")
    }

    private val accounts = if (BuildConfig.DEBUG) { // BuildConfig.DEBUG for dead-code removal
        listOf(
            TestAccount("foo@example.com", "hello"),
            TestAccount("bar@example.com", "world")
        )
    } else {
        emptyList()
    }

    override fun apply(functionDefinition: FunctionDefinition, categoryDefinition: CategoryDefinition): List<SimpleFunctionItem> =
        accounts.map {
            object : SimpleFunctionItem(functionDefinition, categoryDefinition) {
                override val name = it.title
                override val args = listOf(it.email, it.password) // arguments as expected from signInAs(...)
            }
        }
}

The above transformer can also be achieved using @DeveloperArguments.

@DeveloperArguments(
    name = "Authenticate as %0",
    args = [
        Args(["foo@example.com", "hello"]),
        Args(["bar@example.com", "world"])
    ]
)
fun signInAs(...)

Contextual Vars

(experimental) At compile time the follow vars are available for use in value (also DeveloperCategory.value and DeveloperCategory.group):

e.g.

class MyClass {
    @DeveloperFunction("I am in %CLASS_SN%")
    fun someFun() = Unit // name="I am in MyClass"
}

Limitations

Parameters

value - The name that to be shown for this item. If blank the method name will be split by camel case. (e.g. “myFunction” → “My Function”)

category - Category definition override. Unset fields will be inherited.

requiresApi - API required for this item to be visible/processed. Unset or values <= 0 are ignored.

transformer - A transformer class to handle the FunctionDefinition to FunctionItem processing. Defaults to SingleFunctionTransformer.

See Also

DeveloperCategory

FunctionTransformer

SimpleFunctionItem

Constructors

Name Summary
<init> DeveloperFunction(value: String = "", category: DeveloperCategory = DeveloperCategory(), requiresApi: Int = 0, transformer: KClass<out FunctionTransformer> = SingleFunctionTransformer::class)
Functions/methods annotated with this will be shown on the Developer Menu (and other modules).

Properties

Name Summary
category val category: DeveloperCategory
Category definition override. Unset fields will be inherited.
requiresApi val requiresApi: Int
API required for this item to be visible/processed. Unset or values <= 0 are ignored.
transformer val transformer: KClass<out FunctionTransformer>
A transformer class to handle the FunctionDefinition to FunctionItem processing. Defaults to SingleFunctionTransformer.
value val value: String
The name that to be shown for this item. If blank the method name will be split by camel case. (e.g. “myFunction” → “My Function”)