// Copyright (C) 2024 Gradle, Inc.
//
// Licensed under the Creative Commons Attribution-Noncommercial-ShareAlike 4.0 International License.;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://creativecommons.org/licenses/by-nc-sa/4.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.

[[lazy_configuration]]
= Configuring Tasks Lazily

Knowing when and where a particular value is configured is difficult to track as a build grows in complexity.
Gradle provides several ways to manage this using *lazy configuration*.

image::writing-tasks-4.png[]

[[lazy_properties]]
== Understanding Lazy properties

Gradle provides lazy properties, which delay calculating a property’s value until it’s actually required.

Lazy properties provide three main benefits:

1. *Deferred Value Resolution:* Allows wiring Gradle models without needing to know when a property's value will be known.
For example, you may want to set the input source files of a task based on the source directories property of an extension, but the extension property value isn't known until the build script or some other plugin configures them.
2. *Automatic Task Dependency Management:* Connects output of one task to input of another, automatically determining task dependencies.
Property instances carry information about which task, if any, produces their value.
Build authors do not need to worry about keeping task dependencies in sync with configuration changes.
3. *Improved Build Performance:* Avoids resource-intensive work during configuration, impacting build performance positively.
For example, when a configuration value comes from parsing a file but is only used when functional tests are run, using a property instance to capture this means that the file is parsed only when the functional tests are run (and not when `clean` is run, for example).

Gradle represents lazy properties with two interfaces:

link:{javadocPath}/org/gradle/api/provider/Provider.html[Provider] :: Represents a value that can only be queried and cannot be changed.
** Properties with these types are read-only.
** The method link:{javadocPath}/org/gradle/api/provider/Provider.html#get--[Provider.get()] returns the current value of the property.
** A `Provider` can be created from another `Provider` using link:{javadocPath}/org/gradle/api/provider/Provider.html#map-org.gradle.api.Transformer-[Provider.map(Transformer)].
** Many other types extend `Provider` and can be used wherever a `Provider` is required.

link:{javadocPath}/org/gradle/api/provider/Property.html[Property] :: Represents a value that can be queried and changed.
** Properties with these types are configurable.
** `Property` extends the `Provider` interface.
** The method link:{javadocPath}/org/gradle/api/provider/Property.html#set-T-[Property.set(T)] specifies a value for the property, overwriting whatever value may have been present.
** The method link:{javadocPath}/org/gradle/api/provider/Property.html#set-org.gradle.api.provider.Provider-[Property.set(Provider)] specifies a `Provider` for the value for the property, overwriting whatever value may have been present.
This allows you to wire together `Provider` and `Property` instances before the values are configured.
** A `Property` can be created by the factory method link:{javadocPath}/org/gradle/api/model/ObjectFactory.html#property-java.lang.Class-[ObjectFactory.property(Class)].

Lazy properties are intended to be passed around and only queried when required.
This typically happens during the <<build_lifecycle.adoc#sec:build_phases,execution phase>>.

The following demonstrates a task with a configurable `greeting` property and a read-only `message` property:

====
include::sample[dir="snippets/providers/propertyAndProvider/kotlin",files="build.gradle.kts[]"]
include::sample[dir="snippets/providers/propertyAndProvider/groovy",files="build.gradle[]"]
====
<1> A task that displays a greeting
<2> A configurable greeting
<3> Read-only property calculated from the greeting
<4> Configure the greeting
<5> Alternative notation to calling Property.set()

----
$ gradle greeting
include::{snippetsPath}/providers/propertyAndProvider/tests/usePropertyAndProvider.out[]
----

The `Greeting` task has a property of type `Property<String>` to represent the configurable greeting and a property of type `Provider<String>` to represent the calculated, read-only, message.
The message `Provider` is created from the greeting `Property` using the `map()` method; its value is kept up-to-date as the value of the greeting property changes.

[[creating_property_provider]]
== Creating a Property or Provider instance

Neither `Provider` nor its subtypes, such as `Property`, are intended to be implemented by a build script or plugin.
Gradle provides factory methods to create instances of these types instead.

In the previous example, two factory methods were presented:

- link:{javadocPath}/org/gradle/api/model/ObjectFactory.html#property-java.lang.Class-[ObjectFactory.property(Class)] create a new `Property` instance.
An instance of the link:{javadocPath}/org/gradle/api/model/ObjectFactory.html[ObjectFactory] can be referenced from link:{javadocPath}/org/gradle/api/Project.html#getObjects--[Project.getObjects()] or by injecting `ObjectFactory` through a constructor or method.
- link:{javadocPath}/org/gradle/api/provider/Provider.html#map-org.gradle.api.Transformer-[Provider.map(Transformer)] creates a new `Provider` from an existing `Provider` or `Property` instance.

See the <<#lazy_configuration_reference,Quick Reference>> for all of the types and factories available.

A `Provider` can also be created by the factory method link:{groovyDslPath}/org.gradle.api.provider.ProviderFactory.html#org.gradle.api.provider.ProviderFactory:provider(java.util.concurrent.Callable)[ProviderFactory.provider(Callable)].

[NOTE]
====
There are no specific methods to create a provider using a `groovy.lang.Closure`.

When writing a plugin or build script with Groovy, you can use the `map(Transformer)` method with a closure, and Groovy will convert the closure to a `Transformer`.

Similarly, when writing a plugin or build script with Kotlin, the Kotlin compiler will convert a Kotlin function into a `Transformer`.
====

[[connecting_properties_together]]
== Connecting properties together

An important feature of lazy properties is that they can be connected together so that changes to one property are automatically reflected in other properties.

Here is an example where the property of a task is connected to a property of a project extension:

====
include::sample[dir="snippets/providers/connectProperties/kotlin",files="build.gradle.kts[]"]
include::sample[dir="snippets/providers/connectProperties/groovy",files="build.gradle[]"]
====

----
$ gradle greeting
include::{snippetsPath}/providers/connectProperties/tests/connectProperties.out[]
----

This example calls the link:{javadocPath}/org/gradle/api/provider/Property.html#set-org.gradle.api.provider.Provider-[Property.set(Provider)] method to attach a `Provider` to a `Property` to supply the value of the property.
In this case, the `Provider` happens to be a `Property` as well, but you can connect any `Provider` implementation, for example one created using `Provider.map()`

[[working_with_files_in_lazy_properties]]
== Working with files

In <<working_with_files.adoc#working_with_files,Working with Files>>, we introduced four collection types for `File`-like objects:

[%header%autowidth,compact]
|===
| Read-only Type | Configurable Type

| link:{javadocPath}/org/gradle/api/file/FileCollection.html[FileCollection]
| link:{javadocPath}/org/gradle/api/file/ConfigurableFileCollection.html[ConfigurableFileCollection]

| link:{javadocPath}/org/gradle/api/file/FileTree.html[FileTree]
| link:{javadocPath}/org/gradle/api/file/ConfigurableFileTree.html[ConfigurableFileTree]
|===

All of these types are also considered lazy types.

There are more strongly typed models used to represent elements of the file system:
link:{javadocPath}/org/gradle/api/file/Directory.html[Directory] and link:{javadocPath}/org/gradle/api/file/RegularFile.html[RegularFile].
These types shouldn't be confused with the standard Java link:{javaApi}/java/io/File.html[File] type as they are used to tell Gradle that you expect more specific values such as a directory or a non-directory, regular file.

Gradle provides two specialized `Property` subtypes for dealing with values of these types:
link:{javadocPath}/org/gradle/api/file/RegularFileProperty.html[RegularFileProperty] and link:{javadocPath}/org/gradle/api/file/DirectoryProperty.html[DirectoryProperty]. link:{javadocPath}/org/gradle/api/model/ObjectFactory.html[ObjectFactory] has methods to create these: link:{javadocPath}/org/gradle/api/model/ObjectFactory.html#fileProperty--[ObjectFactory.fileProperty()] and link:{javadocPath}/org/gradle/api/model/ObjectFactory.html#directoryProperty--[ObjectFactory.directoryProperty()].

A `DirectoryProperty` can also be used to create a lazily evaluated `Provider` for a `Directory` and `RegularFile` via link:{javadocPath}/org/gradle/api/file/DirectoryProperty.html#dir-java.lang.String-[DirectoryProperty.dir(String)] and link:{javadocPath}/org/gradle/api/file/DirectoryProperty.html#file-java.lang.String-[DirectoryProperty.file(String)] respectively.
These methods create providers whose values are calculated relative to the location for the `DirectoryProperty` they were created from.
The values returned from these providers will reflect changes to the `DirectoryProperty`.

====
include::sample[dir="snippets/providers/fileAndDirectoryProperty/kotlin",files="build.gradle.kts[]"]
include::sample[dir="snippets/providers/fileAndDirectoryProperty/groovy",files="build.gradle[]"]
====

[.multi-language-text.lang-groovy]
----
$ gradle generate
include::{snippetsPath}/providers/fileAndDirectoryProperty/tests/workingWithFilesGroovy.out[]
----
[.multi-language-text.lang-kotlin]
----
$ gradle generate
include::{snippetsPath}/providers/fileAndDirectoryProperty/tests/workingWithFilesKotlin.out[]
----

This example creates providers that represent locations in the project and build directories through link:{javadocPath}/org/gradle/api/Project.html#getLayout--[Project.getLayout()] with link:{javadocPath}/org/gradle/api/file/ProjectLayout.html#getBuildDirectory--[ProjectLayout.getBuildDirectory()] and link:{javadocPath}/org/gradle/api/file/ProjectLayout.html#getProjectDirectory--[ProjectLayout.getProjectDirectory()].

To close the loop, note that a `DirectoryProperty`, or a simple `Directory`, can be turned into a `FileTree` that allows the files and directories contained in the directory to be queried with link:{javadocPath}/org/gradle/api/file/DirectoryProperty.html#getAsFileTree--[DirectoryProperty.getAsFileTree()] or link:{javadocPath}/org/gradle/api/file/Directory.html#getAsFileTree--[Directory.getAsFileTree()].
From a `DirectoryProperty` or a `Directory`, you can create `FileCollection` instances containing a set of the files contained in the directory with link:{javadocPath}/org/gradle/api/file/DirectoryProperty.html#files-java.lang.Object++...++-[DirectoryProperty.files(Object++...++)] or link:{javadocPath}/org/gradle/api/file/Directory.html#files-java.lang.Object++...++-[Directory.files(Object++...++)].

[[working_with_task_dependencies_in_lazy_properties]]
== Working with task inputs and outputs

Many builds have several tasks connected together, where one task consumes the outputs of another task as an input.

To make this work, we need to configure each task to know where to look for its inputs and where to place its outputs.
Ensure that the producing and consuming tasks are configured with the same location and attach task dependencies between the tasks.
This can be cumbersome and brittle if any of these values are configurable by a user or configured by multiple plugins, as task properties need to be configured in the correct order and locations, and task dependencies kept in sync as values change.

The `Property` API makes this easier by keeping track of the value of a property and the task that produces the value.

As an example, consider the following plugin with a producer and consumer task which are wired together:

====
include::sample[dir="snippets/providers/implicitTaskInputFileDependency/kotlin",files="build.gradle.kts[]"]
include::sample[dir="snippets/providers/implicitTaskInputFileDependency/groovy",files="build.gradle[]"]
====

[.multi-language-text.lang-groovy]
----
$ gradle consumer
include::{snippetsPath}/providers/implicitTaskInputFileDependency/tests/implicitTaskInputFileDependencyGroovy.out[]
----
[.multi-language-text.lang-kotlin]
----
$ gradle consumer
include::{snippetsPath}/providers/implicitTaskInputFileDependency/tests/implicitTaskInputFileDependencyKotlin.out[]
----

In the example above, the task outputs and inputs are connected before any location is defined.
The setters can be called at any time before the task is executed, and the change will automatically affect all related input and output properties.

Another important thing to note in this example is the absence of any explicit task dependency.
Task outputs represented using `Providers` keep track of which task produces their value, and using them as task inputs will implicitly add the correct task dependencies.

Implicit task dependencies also work for input properties that are not files:

====
include::sample[dir="snippets/providers/implicitTaskInputDependency/kotlin",files="build.gradle.kts[]"]
include::sample[dir="snippets/providers/implicitTaskInputDependency/groovy",files="build.gradle[]"]
====

[.multi-language-text.lang-groovy]
----
$ gradle consumer
include::{snippetsPath}/providers/implicitTaskInputDependency/tests/implicitTaskInputDependencyGroovy.out[]
----
[.multi-language-text.lang-kotlin]
----
$ gradle consumer
include::{snippetsPath}/providers/implicitTaskInputDependency/tests/implicitTaskInputDependencyKotlin.out[]
----

[[working_with_collections]]
== Working with collections

Gradle provides two lazy property types to help configure `Collection` properties.

These work exactly like any other `Provider` and, just like file providers, they have additional modeling around them:

* For `List` values the interface is called link:{javadocPath}/org/gradle/api/provider/ListProperty.html[ListProperty]. +
You can create a new `ListProperty` using link:{javadocPath}/org/gradle/api/model/ObjectFactory.html#listProperty-java.lang.Class-[ObjectFactory.listProperty(Class)] and specifying the element type.
* For `Set` values the interface is called link:{javadocPath}/org/gradle/api/provider/SetProperty.html[SetProperty]. +
You can create a new `SetProperty` using link:{javadocPath}/org/gradle/api/model/ObjectFactory.html#setProperty-java.lang.Class-[ObjectFactory.setProperty(Class)] and specifying the element type.

This type of property allows you to overwrite the entire collection value with link:{javadocPath}/org/gradle/api/provider/HasMultipleValues.html#set-java.lang.Iterable-[HasMultipleValues.set(Iterable)] and link:{javadocPath}/org/gradle/api/provider/HasMultipleValues.html#set-org.gradle.api.provider.Provider-[HasMultipleValues.set(Provider)] or add new elements through the various `add` methods:

* link:{javadocPath}/org/gradle/api/provider/HasMultipleValues.html#add-T-[HasMultipleValues.add(T)]: Add a single element to the collection
* link:{javadocPath}/org/gradle/api/provider/HasMultipleValues.html#add-org.gradle.api.provider.Provider-[HasMultipleValues.add(Provider)]: Add a lazily calculated element to the collection
* link:{javadocPath}/org/gradle/api/provider/HasMultipleValues.html#addAll-org.gradle.api.provider.Provider-[HasMultipleValues.addAll(Provider)]: Add a lazily calculated collection of elements to the list

Just like every `Provider`, the collection is calculated when link:{javadocPath}/org/gradle/api/provider/Provider.html#get--[Provider.get()] is called. The following example shows the link:{javadocPath}/org/gradle/api/provider/ListProperty.html[ListProperty] in action:

====
include::sample[dir="snippets/providers/listProperty/kotlin",files="build.gradle.kts[]"]
include::sample[dir="snippets/providers/listProperty/groovy",files="build.gradle[]"]
====

[.multi-language-text.lang-groovy]
----
$ gradle consumer
include::{snippetsPath}/providers/listProperty/tests/listPropertyGroovy.out[]
----
[.multi-language-text.lang-kotlin]
----
$ gradle consumer
include::{snippetsPath}/providers/listProperty/tests/listPropertyKotlin.out[]
----

[[working_with_maps]]
== Working with maps

Gradle provides a lazy link:{javadocPath}/org/gradle/api/provider/MapProperty.html[MapProperty] type to allow `Map` values to be configured.
You can create a `MapProperty` instance using link:{javadocPath}/org/gradle/api/model/ObjectFactory.html#mapProperty-java.lang.Class-java.lang.Class-[ObjectFactory.mapProperty(Class, Class)].

Similar to other property types, a `MapProperty` has a link:{javadocPath}/org/gradle/api/provider/MapProperty.html#set-java.util.Map-[set()] method that you can use to specify the value for the property.
Some additional methods allow entries with lazy values to be added to the map.

====
include::sample[dir="snippets/providers/mapProperty/kotlin",files="build.gradle.kts[]"]
include::sample[dir="snippets/providers/mapProperty/groovy",files="build.gradle[]"]
====

----
$ gradle generate
include::{snippetsPath}/providers/mapProperty/tests/mapProperty.out[]
----

[[applying_conventions]]
== Applying a convention to a property

Often, you want to apply some _convention_, or default value to a property to be used if no value has been configured.
You can use the `convention()` method for this.
This method accepts either a value or a `Provider`, and this will be used as the value until some other value is configured.

====
include::sample[dir="snippets/providers/propertyConvention/kotlin",files="build.gradle.kts[tags=conventions]"]
include::sample[dir="snippets/providers/propertyConvention/groovy",files="build.gradle[tags=conventions]"]
====

----
$ gradle show
include::{snippetsPath}/providers/propertyConvention/tests/propertyConvention.out[]
----

=== Where to apply conventions from?

There are several appropriate locations for setting a convention on a property at configuration time (i.e., before execution).

====
include::sample[dir="snippets/providers/propertyConventionCallsites/kotlin",files="build.gradle.kts[tags=convention-callsites]"]
include::sample[dir="snippets/providers/propertyConventionCallsites/groovy",files="build.gradle[tags=convention-callsites]"]
====

==== From a plugin's `apply()` method

Plugin authors may configure a convention on a lazy property from a plugin's `apply()` method, while performing preliminary configuration of the task or extension defining the property.
This works well for regular plugins (meant to be distributed and used in the wild), and internal <<sharing_build_logic_between_subprojects.adoc#sec:sharing_logic_via_convention_plugins,convention plugins>> (which often configure properties defined by third party plugins in a uniform way for the entire build).

====
include::sample[dir="snippets/providers/propertyConventionCallsites/kotlin",files="build.gradle.kts[tags=convention-callsites-from-plugin]"]
include::sample[dir="snippets/providers/propertyConventionCallsites/groovy",files="build.gradle[tags=convention-callsites-from-plugin]"]
====

==== From a build script

Build engineers may configure a convention on a lazy property from shared build logic that is configuring tasks (for instance, from third-party plugins) in a standard way for the entire build.

====
include::sample[dir="snippets/providers/propertyConventionCallsites/kotlin",files="build.gradle.kts[tags=convention-callsites-from-buildscript]"]
include::sample[dir="snippets/providers/propertyConventionCallsites/groovy",files="build.gradle[tags=convention-callsites-from-buildscript]"]
====

Note that for project-specific values, instead of conventions, you should prefer setting explicit values (using `Property.set(...)` or `ConfigurableFileCollection.setFrom(...)`, for instance),
as conventions are only meant to define defaults.

==== From the task initialization

A task author may configure a convention on a lazy property from the task constructor or (if in Kotlin) initializer block.
This approach works for properties with trivial defaults, but it is not appropriate if additional context (external to the task implementation) is required in order to set a suitable default.

====
include::sample[dir="snippets/providers/propertyConventionCallsites/kotlin",files="build.gradle.kts[tags=convention-callsites-from-constructor]"]
include::sample[dir="snippets/providers/propertyConventionCallsites/groovy",files="build.gradle[tags=convention-callsites-from-constructor]"]
====

==== Next to the property declaration

You may configure a convention on a lazy property next to the place where the property is declared.
Note this option is not available for <<properties_providers.adoc#managed_properties,managed properties>>, and has the same caveats as configuring a convention from the task constructor.

====
include::sample[dir="snippets/providers/propertyConventionCallsites/kotlin",files="build.gradle.kts[tags=convention-callsites-from-declaration]"]
include::sample[dir="snippets/providers/propertyConventionCallsites/groovy",files="build.gradle[tags=convention-callsites-from-declaration]"]
====


[[unmodifiable_property]]
== Making a property unmodifiable

Most properties of a task or project are intended to be configured by plugins or build scripts so that they can use specific values for that build.

For example, a property that specifies the output directory for a compilation task may start with a value specified by a plugin.
Then a build script might change the value to some custom location, then this value is used by the task when it runs.
However, once the task starts to run, we want to prevent further property changes.
This way we avoid errors that result from different consumers, such as the task action, Gradle's up-to-date checks, build caching, or other tasks, using different values for the property.

Lazy properties provide several methods that you can use to disallow changes to their value once the value has been configured.
The link:{javadocPath}/org/gradle/api/provider/Property.html#finalizeValue--[finalizeValue()] method calculates the _final_ value for the property and prevents further changes to the property.

```
libVersioning.version.finalizeValue()
```

When the property's value comes from a `Provider`, the provider is queried for its current value, and the result becomes the final value for the property.
This final value replaces the provider and the property no longer tracks the value of the provider.
Calling this method also makes a property instance unmodifiable and any further attempts to change the value of the property will fail.
Gradle automatically makes the properties of a task final when the task starts execution.

The link:{javadocPath}/org/gradle/api/provider/HasConfigurableValue.html#finalizeValueOnRead--[finalizeValueOnRead()] method is similar, except that the property's final value is not calculated until the value of the property is queried.

```
modifiedFiles.finalizeValueOnRead()
```

In other words, this method calculates the final value lazily as required, whereas `finalizeValue()` calculates the final value eagerly.
This method can be used when the value may be expensive to calculate or may not have been configured yet.
You also want to ensure that all consumers of the property see the same value when they query the value.

[[lazy_configuration_faqs]]
== Using the Provider API

Guidelines to be successful with the Provider API:

1. The link:{javadocPath}/org/gradle/api/provider/Property.html[Property] and link:{javadocPath}/org/gradle/api/provider/Provider.html[Provider] types have all of the overloads you need to query or configure a value. For this reason, you should follow the following guidelines:
** For configurable properties, expose the link:{javadocPath}/org/gradle/api/provider/Property.html[Property] directly through a single getter.
** For non-configurable properties, expose an link:{javadocPath}/org/gradle/api/provider/Provider.html[Provider] directly through a single getter.

2. Avoid simplifying calls like `obj.getProperty().get()` and `obj.getProperty().set(T)` in your code by introducing additional getters and setters.

3. When migrating your plugin to use providers, follow these guidelines:
** If it's a new property, expose it as a link:{javadocPath}/org/gradle/api/provider/Property.html[Property] or link:{javadocPath}/org/gradle/api/provider/Provider.html[Provider] using a single getter.
** If it's incubating, change it to use a link:{javadocPath}/org/gradle/api/provider/Property.html[Property] or link:{javadocPath}/org/gradle/api/provider/Provider.html[Provider] using a single getter.
** If it's a stable property, add a new link:{javadocPath}/org/gradle/api/provider/Property.html[Property] or link:{javadocPath}/org/gradle/api/provider/Provider.html[Provider] and deprecate the old one. You should wire the old getter/setters into the new property as appropriate.

[[lazy_configuration_reference]]
=== Provider Files API Reference

Use these types for _read-only_ values:

link:{javadocPath}/org/gradle/api/provider/Provider.html[Provider]<link:{javadocPath}/org/gradle/api/file/RegularFile.html[RegularFile]>:: File on disk
Factories;;
* link:{javadocPath}/org/gradle/api/provider/Provider.html#map-org.gradle.api.Transformer-[Provider.map(Transformer)].
* link:{javadocPath}/org/gradle/api/provider/Provider.html#flatMap-org.gradle.api.Transformer-[Provider.flatMap(Transformer)].
* link:{javadocPath}/org/gradle/api/file/DirectoryProperty.html#file-java.lang.String-[DirectoryProperty.file(String)]

link:{javadocPath}/org/gradle/api/provider/Provider.html[Provider]<link:{javadocPath}/org/gradle/api/file/Directory.html[Directory]>:: Directory on disk
Factories;;
* link:{javadocPath}/org/gradle/api/provider/Provider.html#map-org.gradle.api.Transformer-[Provider.map(Transformer)].
* link:{javadocPath}/org/gradle/api/provider/Provider.html#flatMap-org.gradle.api.Transformer-[Provider.flatMap(Transformer)].
* link:{javadocPath}/org/gradle/api/file/DirectoryProperty.html#dir-java.lang.String-[DirectoryProperty.dir(String)]

link:{javadocPath}/org/gradle/api/file/FileCollection.html[FileCollection]:: Unstructured collection of files
Factories;;
* link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:files(java.lang.Object++[]++)[Project.files(Object++[]++)]
    * link:{javadocPath}/org/gradle/api/file/ProjectLayout.html#files-java.lang.Object++...++-[ProjectLayout.files(Object++...++)]
    * link:{javadocPath}/org/gradle/api/file/DirectoryProperty.html#files-java.lang.Object++...++-[DirectoryProperty.files(Object++...++)]

link:{javadocPath}/org/gradle/api/file/FileTree.html[FileTree]:: Hierarchy of files
Factories;;
* link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:fileTree(java.lang.Object)[Project.fileTree(Object)] will produce a link:{javadocPath}/org/gradle/api/file/ConfigurableFileTree.html[ConfigurableFileTree], or you can use link:{javadocPath}/org/gradle/api/Project.html#zipTree-java.lang.Object-[Project.zipTree(Object)] and link:{javadocPath}/org/gradle/api/Project.html#tarTree-java.lang.Object-[Project.tarTree(Object)]
* link:{javadocPath}/org/gradle/api/file/DirectoryProperty.html#getAsFileTree--[DirectoryProperty.getAsFileTree()]

=== Property Files API Reference

Use these types for _mutable_ values:

link:{javadocPath}/org/gradle/api/file/RegularFileProperty.html[RegularFileProperty]:: File on disk
Factories;;
* link:{javadocPath}/org/gradle/api/model/ObjectFactory.html#fileProperty--[ObjectFactory.fileProperty()]

link:{javadocPath}/org/gradle/api/file/DirectoryProperty.html[DirectoryProperty]:: Directory on disk
Factories;;
* link:{javadocPath}/org/gradle/api/model/ObjectFactory.html#directoryProperty--[ObjectFactory.directoryProperty()]

link:{javadocPath}/org/gradle/api/file/ConfigurableFileCollection.html[ConfigurableFileCollection]:: Unstructured collection of files
Factories;;
* link:{javadocPath}/org/gradle/api/model/ObjectFactory.html#fileCollection--[ObjectFactory.fileCollection()]

link:{javadocPath}/org/gradle/api/file/ConfigurableFileTree.html[ConfigurableFileTree]:: Hierarchy of files
Factories;;
* link:{javadocPath}/org/gradle/api/model/ObjectFactory.html#fileTree--[ObjectFactory.fileTree()]

link:{javadocPath}/org/gradle/api/file/SourceDirectorySet.html[SourceDirectorySet]:: Hierarchy of source directories
Factories;;
* link:{javadocPath}/org/gradle/api/model/ObjectFactory.html#sourceDirectorySet-java.lang.String-java.lang.String-[ObjectFactory.sourceDirectorySet(String, String)]

=== Lazy Collections API Reference

Use these types for _mutable_ values:

link:{javadocPath}/org/gradle/api/provider/ListProperty.html[ListProperty<T>]:: a property whose value is `List<T>`
Factories;;
* link:{javadocPath}/org/gradle/api/model/ObjectFactory.html#listProperty-java.lang.Class-[ObjectFactory.listProperty(Class)]

link:{javadocPath}/org/gradle/api/provider/SetProperty.html[SetProperty<T>]:: a property whose value is `Set<T>`
Factories;;
* link:{javadocPath}/org/gradle/api/model/ObjectFactory.html#setProperty-java.lang.Class-[ObjectFactory.setProperty(Class)]

=== Lazy Objects API Reference

Use these types for _read only_ values:

link:{javadocPath}/org/gradle/api/provider/Provider.html[Provider<T>]:: a property whose value is an instance of `T`
Factories;;
* link:{javadocPath}/org/gradle/api/provider/Provider.html#map-org.gradle.api.Transformer-[Provider.map(Transformer)].
* link:{javadocPath}/org/gradle/api/provider/Provider.html#flatMap-org.gradle.api.Transformer-[Provider.flatMap(Transformer)].
* link:{groovyDslPath}/org.gradle.api.provider.ProviderFactory.html#org.gradle.api.provider.ProviderFactory:provider(java.util.concurrent.Callable)[ProviderFactory.provider(Callable)]. Always prefer one of the other factory methods over this method.

Use these types for _mutable_ values:

link:{javadocPath}/org/gradle/api/provider/Property.html[Property<T>]:: a property whose value is an instance of `T`
Factories;;
* link:{javadocPath}/org/gradle/api/model/ObjectFactory.html#property-java.lang.Class-[ObjectFactory.property(Class)]
