saker.build
saker.build copied to clipboard
Context based build task invocation
Feature description
The build tasks in the script could be declared based on the enclosing task context. It should reduce the boilerplate that surrounds a task invocation. E.g.:
some.task(
Configuration: .config(data),
# note the two dots
Parameter: ..foo.bar(baz),
)
The above would be equivalent to:
some.task(
Configuration: some.task.config(data),
Parameter: some.foo.bar(baz),
)
Starting a task declaration with a dot can mean that the following task identifier is to be interpreted against the enclosing task.
Workarounds Use fully qualified task names.
Use-case For long task names this can reduce the boilerplate surrounding it. This is mostly prevalent when tasks are called in a way that they can be configured with other tasks that bear the same name.
Non-goals
The solution should not take multiple levels of task declarations into account. The solution should only be a syntactic enhancement, and the behaviour of actual task invocation and name resolution should not change.
Other aspects
We should also examine how this feature integrates with task names. Whether or not we should allow multiple dots at the start of task identifiers, and what may be the limit of it. In other aspects, we may not want to use too many preceeding dots, as that would limit readability.
Two-dot examples
Some examples that justify allowing multiple preceeding dots:
saker.java.compile(
ClassPath: ..classpath.bundle(bundle.name-v1.2.3),
AnnotationProcessors: [
..processor(lib/myprocessor.jar)
]
)
nest.dependency.resolve(
some.bundle,
Filters: [
..filter.kind(classpath),
..filter.compile(CompileTransitive: false)
]
)
Often the related tasks are not a direct continuation of the enclosing task, as the above example showcases.
We should also note that if we allow multiple preceeding dots, we need to allow more than two. Restricting it to a maximum number would be only an opinionated restriction for readability and has no technical reasons at all.
We should let the developers use as many dots as they want, but strongly recommend them to keep them at minimum.
The above example without the feature would look like:
saker.java.compile(
ClassPath: saker.java.classpath.bundle(bundle.name-v1.2.3),
AnnotationProcessors: [
saker.java.processor(lib/myprocessor.jar)
]
)
nest.dependency.resolve(
some.bundle,
Fiilters: [
nest.dependency.filter.kind(classpath),
nest.dependency.filter.compile(CompileTransitive: false)
]
)
Another example is when dealing with Maven tasks:
saker.maven.deploy(
RemoteRepository: {
Authentication: ..auth.account(
Username: foo,
Password: bar,
)
},
)
We can also realize that by using context based task declaration, the copiableness of the code parts are reduced. You cannot simply copy script parts that contain context based tasks and paste them to other locations as that may have different meanings.
The upcoming process related build tasks can also take advantage of this:
proc.run([
java,
-cp,
..arg.in.file(### ... ###),
..arg.out.file(### ... ###)
])
Based on the above, it would be great if there was a solution that allowed us to omit the ..arg
part of the inner tasks. Something like this:
proc.run([
java,
-cp,
.in.file(### ... ###),
.out.file(### ... ###)
])
Maybe some way where it is included in the parameter name? e.g:
proc.run(Command..arg: [
java,
-cp,
.in.file(### ... ###),
.out.file(### ... ###)
])
Where the ..arg
part specifies that the enclosed context based declarations start with ..arg
. In its current form it is not straightforward and I wouldn't consider it to be readable, so this is only for brainstorming.