Skip to content

TaskAnalyzer: no diagnostic when a task constructs another ITask without propagating TaskEnvironment #14792

Description

@ViktorHofer

Summary

A task that constructs another task instance directly does not get TaskEnvironment propagated into it. MSBuild only injects into tasks it instantiates itself (TaskExecutionHost.cs), so the inner task silently falls back to TaskEnvironment.Fallback and resolves paths against the shared node's current directory.

There is no diagnostic for this, and it is invisible to every existing rule because the outer task looks fully migrated.

Evidence

From dotnet/arcade ExecWithRetries:

_runningExec = new Exec
{
    BuildEngine = BuildEngine,
    Command = Command,
    WorkingDirectory = WorkingDirectory,   // resolved by ToolTask via *its* TaskEnvironment
    ...
};

Exec derives from ToolTask, which uses TaskEnvironment for both WorkingDirectory and GetProcessStartInfo(). The outer task was annotated, used TaskEnvironment correctly everywhere in its own body, and passed the analyzer cleanly — while handing the real work to an inner task that had no environment at all.

The fix is a one-liner, which is what makes the missing diagnostic worth having:

_runningExec = new Exec
{
    BuildEngine = BuildEngine,
    TaskEnvironment = TaskEnvironment,   // <-- required
    ...
};

Proposed rule

Inside a type that is [MSBuildMultiThreadableTask]-annotated (or implements IMultiThreadableTask), flag an object-creation expression whose type implements ITask when TaskEnvironment is not assigned — via object initializer, property assignment, or constructor.

Severity: Warning. The false-positive rate should be near zero, since constructing an ITask inside a task is rare and always needs this.

Note that ToolTask.TaskEnvironment is public virtual, so the fix is always expressible; a code fix that adds the initializer entry would be straightforward.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions