Skip to content

Core support for AbsolutePath/FileInfo/DirectoryInfo and ITaskItem<T> as task parameters#13971

Open
baronfel wants to merge 24 commits into
mainfrom
typed-params/core
Open

Core support for AbsolutePath/FileInfo/DirectoryInfo and ITaskItem<T> as task parameters#13971
baronfel wants to merge 24 commits into
mainfrom
typed-params/core

Conversation

@baronfel

@baronfel baronfel commented Jun 5, 2026

Copy link
Copy Markdown
Member

Summary

Adds support for using AbsolutePath, System.IO.FileInfo, System.IO.DirectoryInfo, and ITaskItem (for path-like T) as MSBuild task input/output parameters, in addition to the existing string and ITaskItem types.

Changes

  • AbsolutePath: A new value type that wraps an absolute path string, validated via TaskEnvironment.GetAbsolutePath
  • FileInfo / DirectoryInfo: Paths are validated as absolute before creating the FileInfo/DirectoryInfo instance
  • ITaskItem<T>: A new generic interface allowing typed access to item specs, with T restricted to AbsolutePath, FileInfo, or DirectoryInfo in this PR
  • TaskItem<T>: Implementation of ITaskItem with mutable metadata backing
  • ValueTypeParser: Shared utility for parsing/formatting typed values (infrastructure for future PRs)
  • Task host serialization support for typed outputs
  • Full test coverage for all new parameter types

Stacked on

/cc @baronfel

@baronfel baronfel changed the title typed params/core Core support for AbsolutePath/FileInfo/DirectoryInfo and ITaskItem<T> as task parameters Jun 5, 2026
@baronfel baronfel marked this pull request as ready for review June 5, 2026 19:48
Copilot AI review requested due to automatic review settings June 5, 2026 19:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds core infrastructure to support strongly-typed MSBuild task parameters and outputs for path-like values, including a new AbsolutePath-based flow, FileInfo/DirectoryInfo binding, and generic task items (ITaskItem<T> / TaskItem<T>). This primarily touches the task parameter binding pipeline (TaskExecutionHost), parameter type validation/serialization (TaskParameter*), and adds corresponding unit tests + docs updates.

Changes:

  • Introduces ITaskItem<T> (Framework) and TaskItem<T> (Utilities) to enable typed item identities.
  • Adds ValueTypeParser and switches task output serialization to a canonical string conversion path.
  • Extends TaskExecutionHost binding + unit tests to cover AbsolutePath, FileInfo/DirectoryInfo, and typed task items.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/Utilities/TaskItem_T.cs New TaskItem<T> struct implementing typed task items over an ITaskItem backing instance.
src/Utilities.UnitTests/TaskItem_Tests.cs Unit tests for TaskItem<T> metadata behavior and parsing behavior.
src/Tasks/Microsoft.Build.Tasks.csproj Minor ItemGroup structure tweak.
src/Shared/ValueTypeParser.cs New shared parser/formatter for value-like task parameter conversions.
src/Shared/UnitTests/TaskParameter_Tests.cs Adds serialization tests for AbsolutePath / FileInfo / DirectoryInfo.
src/Shared/TaskParameterTypeVerifier.cs Extends supported parameter types to include typed items and path-related types.
src/Shared/TaskParameter.cs Updates value-type output serialization to use ValueTypeParser and support FileInfo/DirectoryInfo.
src/Framework/Microsoft.Build.Framework.csproj Links ValueTypeParser.cs into Framework build.
src/Framework/ITaskItem_T.cs New public ITaskItem<T> interface.
src/Build/Microsoft.Build.csproj Adds Build → Utilities project reference (to use TaskItem<T>).
src/Build/BackEnd/TaskExecutionHost/TaskExecutionHost.cs Adds parameter binding + output gathering support for typed path parameters and typed task items.
src/Build.UnitTests/BackEnd/TaskParameterTypeVerifier_Tests.cs New tests covering typed parameter validation scenarios.
src/Build.UnitTests/BackEnd/TaskExecutionHost_Tests.cs Expanded tests for new parameter types and typed task items.
src/Build.UnitTests/BackEnd/TaskBuilderTestTask.cs Adds test task properties/outputs for new supported parameter types.
documentation/wiki/Tasks.md Updates docs for supported task parameter types.

Comment thread src/Framework/ValueTypeParser.cs
Comment thread src/Utilities/TaskItem_T.cs Outdated
Comment thread src/Utilities/TaskItem_T.cs
Comment thread documentation/wiki/Tasks.md Outdated
Comment thread src/Framework/ITaskItem_T.cs Outdated
Comment thread src/Shared/UnitTests/TaskParameter_Tests.cs
Comment thread src/Shared/UnitTests/TaskParameter_Tests.cs
Comment thread src/Build.UnitTests/BackEnd/TaskParameterTypeVerifier_Tests.cs
Comment thread src/Build.UnitTests/BackEnd/TaskExecutionHost_Tests.cs
@baronfel baronfel requested a review from a team June 8, 2026 15:00

@jankratochvilcz jankratochvilcz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a few comments. The biggest thing we should discuss is whether this is the only architecture viable in the codebase - It would be great to ideate if we can have a more self-contained implementation.

Comment thread src/Build/BackEnd/TaskExecutionHost/TaskExecutionHost.cs Outdated
Comment thread src/Build/BackEnd/TaskExecutionHost/TaskExecutionHost.cs Outdated
Comment thread src/Build/BackEnd/TaskExecutionHost/TaskExecutionHost.cs
Comment thread src/Build/BackEnd/TaskExecutionHost/TaskExecutionHost.cs Outdated
Comment thread src/Build/BackEnd/TaskExecutionHost/TaskExecutionHost.cs Outdated
Comment thread src/Build.UnitTests/BackEnd/TaskExecutionHost_Tests.cs
Comment thread src/MSBuildTaskHost/BackEnd/TaskParameterTypeVerifier.cs Outdated
Comment thread src/Shared/TaskItemTypeHelper.cs Outdated
Comment thread src/Framework/ValueTypeParser.cs
Comment thread documentation/wiki/Tasks.md Outdated
Comment thread documentation/wiki/Tasks.md Outdated
Comment thread documentation/wiki/Tasks.md Outdated
Comment thread src/Framework/ITaskItem_T.cs Outdated
Comment thread src/Framework/ITaskItem_T.cs Outdated
Comment thread src/Framework/ITaskItem_T.cs Outdated
Comment thread src/Framework/ValueTypeParser.cs
Comment thread src/MSBuildTaskHost/MSBuildTaskHost.csproj
Comment thread src/Shared/TaskParameterTypeVerifier.cs Outdated
Comment thread src/Shared/TaskParameterValueStringConverter.cs Outdated
baronfel and others added 17 commits June 17, 2026 13:53
The TASKHOST define is no longer set by any project in the main
codebase since the .NET 3.5 taskhost was separated into a frozen
project. These guards were always evaluating to true.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The out-of-proc task host gathers all [Output] properties and serializes them via TaskParameter. The PR's new AbsolutePath/FileInfo/DirectoryInfo outputs crashed the node: AbsolutePath (a struct) is never null so it always serialized, and Convert.ChangeType threw InvalidCastException because it is not IConvertible; FileInfo/DirectoryInfo additionally hit Assumed.Unreachable in the constructor.

Route FileInfo/DirectoryInfo (scalar and array) to ValueType/ValueTypeArray, and convert values on the write side using ValueTypeParser.ToString - the same canonical conversion the in-process engine uses in TaskExecutionHost.GetValueOutputs - so in-proc and out-of-proc produce identical strings. Harden ValueTypeParser.ToString for a default AbsolutePath (null Value). The legacy net35 task host is intentionally untouched.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Unwrap TargetInvocationException in CreateTaskItemOfT so that parse
errors from value-type constructors surface as the original exception
(typically InvalidProjectFileException) rather than being wrapped in
TargetInvocationException, which was swallowed by the outer catch.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
TaskItemData throws InvalidOperationException on all write operations
(SetMetadata, RemoveMetadata, CopyMetadataTo). Switch the TaskItem<T>(T)
constructor to use Utilities.TaskItem as the backing item, which
supports full metadata mutation as expected by ITaskItem consumers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When constructing TaskItem<T> from an ITaskItem where T is FileInfo,
DirectoryInfo, or AbsolutePath, prefer the FullPath metadata (which
the MSBuild item system computes as an absolute rooted path) over
ItemSpec, which may be a relative path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace Value?.Equals(other.Value) with EqualityComparer<T>.Default.Equals
to avoid boxing for value types, correctly handle null reference types,
and use the appropriate comparer for each type T.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The code already correctly handles ITaskItem<T>[] for both input
(IsValidVectorInputParameter) and output (IsAssignableToITaskItem),
but had no explicit test coverage. Add tests for all four methods
covering scalar and array ITaskItem<T> to prevent future regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Treat arrays with ITaskItem-implementing element types as assignable outputs so TaskItem<T>[] follows the item-output path consistently with TaskExecutionHost behavior. Add unit tests covering TaskItem<int>[] assignability and output validity.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…nfo, DirectoryInfo) in PR1

Value-type T (int, bool, etc.) support for ITaskItem<T> will be added in a subsequent PR.
Also remove ITaskItem<int> tests from PR1 test files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Move TaskExecutionHost's duplicated path-like TaskItem<T>/ITaskItem<T>
helper logic into TaskParameterTypeVerifier so type checks and typed
item construction are centralized and reusable.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
baronfel and others added 4 commits June 17, 2026 13:53
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Rename ITaskItem_T.cs to ITaskItem`1.cs; file-scoped namespace
- Move ValueTypeParser into Framework
- Revert net35 task-host typed-parameter support
- Refactor TaskParameterTypeVerifier with s_supportedTypes switch
- Remove reflection in TaskParameterValueStringConverter
- Consolidate string-to-value conversion via ConvertStringToParameterValue
- Flatten GetItemOutputs with early returns
- Rename TaskItemTypeHelper to TaskItemTypeDetector
- Remove low-value comments; trim docs

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@baronfel baronfel force-pushed the typed-params/core branch from a4d536e to b62b5ae Compare June 17, 2026 18:53
@baronfel baronfel requested a review from jankratochvilcz June 17, 2026 19:17
The inlined reflection passed the closed TaskItem<T>/ITaskItem<T> type to
MakeGenericType instead of its generic argument, producing
TaskItem<TaskItem<FileInfo>> instead of TaskItem<FileInfo>. This broke
TaskExecutionHost_Tests for path-like ITaskItem<T>/TaskItem<T> parameters
with 'Cannot parse ... as type ITaskItem\1'. Extract GetGenericArguments()[0]
before constructing the closed type.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@baronfel

Copy link
Copy Markdown
Member Author

Remaining test failures are buildcheck related - I can't repro locally, but I also haven't been able to collect binlogs from these tests in the CI pipelines.

Adds an opt-in TestEnvironment mechanism to publish files (e.g. binary logs from out-of-process MSBuild invocations) as CI build artifacts. On cleanup, registered files are copied into artifacts/log/<Config>/TestArtifacts (already published by CI), attached to the xUnit result best-effort, and logged. Publication is failure-gated by default via xUnit v3 TestContext, with an 'always' override.

Wires the BuildCheck binary-log EndToEndTests to register their binlogs so out-of-process failures are diagnosable in CI.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants