Skip to content

File-based apps: ensure shebang analyzer only applies to #:include - #54397

Merged
jjonescz merged 7 commits into
dotnet:release/10.0.4xxfrom
jjonescz:sprint-shebang-analyzer-break
Jun 1, 2026
Merged

jjonescz merged 7 commits into
dotnet:release/10.0.4xxfrom
jjonescz:sprint-shebang-analyzer-break

Conversation

@jjonescz

Copy link
Copy Markdown
Member

To avoid breaking people that include .cs files via other means. See #53749 (comment).

@jjonescz
jjonescz requested a review from Copilot May 21, 2026 13:00
@jjonescz jjonescz added the Area-run-file Items related to the "dotnet run <file>" effort label May 21, 2026

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

This PR narrows the CA2266 (“missing shebang in file-based program”) behavior so it only triggers when additional C# source files are brought in via #:include, avoiding warnings for multi-file compilations caused by other MSBuild mechanisms (e.g., Directory.Build.props, project references, etc.).

Changes:

  • Emit compiler-visible item metadata in the generated virtual project so analyzers can distinguish #:include-added Compile items.
  • Update the CA2266 analyzer logic to only warn when a non-entrypoint syntax tree is marked as coming from #:include.
  • Adjust/extend CLI and analyzer unit tests to validate the new behavior and the generated project content.

Reviewed changes

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

Show a summary per file
File Description
test/dotnet.Tests/CommandTests/Run/RunFileTests_Directives.cs Updates API-based virtual project assertions to require the new compiler-visible metadata declaration.
test/dotnet.Tests/CommandTests/Run/RunFileTests_CscOnlyAndApi.cs Updates expected virtual project XML in CscOnly/API tests to include the compiler-visible metadata item.
test/dotnet.Tests/CommandTests/Run/RunFileTests_BuildOptions.cs Updates CA2266 expectations to ensure no warning from extra Compile items added via Directory.Build.props, while still warning for real #:include.
src/Microsoft.DotNet.ProjectTools/VirtualProjectBuilder.cs Adds <CompilerVisibleItemMetadata ...> so FileBasedProgramsFromIncludeDirective flows into analyzer config as build_metadata.Compile.*.
src/Microsoft.CodeAnalysis.NetAnalyzers/tests/.../MissingShebangInFileBasedProgramTests.cs Updates/extends analyzer tests to cover “include vs non-include extra file” behavior.
src/Microsoft.CodeAnalysis.NetAnalyzers/src/.../CSharpMissingShebangInFileBasedProgram.cs Changes CA2266 triggering condition to require presence of build_metadata.Compile.FileBasedProgramsFromIncludeDirective=true on at least one non-entrypoint tree.

@jjonescz
jjonescz marked this pull request as ready for review May 22, 2026 13:56
@jjonescz
jjonescz requested a review from a team as a code owner May 22, 2026 13:56
@jjonescz
jjonescz requested a review from a team May 22, 2026 13:56
@jjonescz

Copy link
Copy Markdown
Member Author

@RikkiGibson @333fred for reviews, thanks

@jjonescz
jjonescz requested a review from RikkiGibson May 27, 2026 06:54
@jjonescz

Copy link
Copy Markdown
Member Author

@RikkiGibson for another review, thanks

});
}

private static bool IsFromIncludeDirective(SyntaxTree tree, AnalyzerConfigOptionsProvider optionsProvider)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Since we now only want to detect when an #:include happens to be the mechanism including the other file, did you consider making this a syntactic check instead? i.e. just look for an ignored directive whose content starts with include ?

@RikkiGibson RikkiGibson May 28, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Perhaps we want to preserve the ability to #:include Config/* and similar, which won't expand into anything that includes .cs, and not tell user to add #! in that case? If so, is there a test for that scenario? I didn't see one from a brief search.

@jjonescz jjonescz May 29, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

did you consider making this a syntactic check instead? i.e. just look for an ignored directive whose content starts with include ?

That's an interesting idea, I did not consider that.

Perhaps we want to preserve the ability to #:include Config/* and similar, which won't expand into anything that includes .cs, and not tell user to add #! in that case?

That really depends on IDE, but yes, I think y'all don't care about non-.cs included files?

If that's indeed the case, I think this cannot be a syntactic check. Even though the #:include directives must have an extension, it can be dynamically mapped (or even need expansion from msbuild properties), so it couldn't be detected from syntax only.

But perhaps we don't need to be that precise (and complex) and we can warn for any #:include really, even if IDE would work in cases where only non-.cs files are included.

If so, is there a test for that scenario? I didn't see one from a brief search.

I will add one, thanks.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

But perhaps we don't need to be that precise (and complex) and we can warn for any #:include really

I like the simplicity of this, I'm going to implement that.

@RikkiGibson RikkiGibson May 29, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That really depends on IDE, but yes, I think y'all don't care about non-.cs included files?

Not 100% sure whether *.cs is the only extension IDE cares about.
Are people going to do #:include Views/*.razor or similar, and expect to get semantic info in the razor files which relates to the rest of the project?

I think erring on the side of making people add #!, even though we strictly could handle the #:include without it, sounds good.

@jjonescz
jjonescz requested review from 333fred and RikkiGibson May 29, 2026 08:42
var filePath = tree.FilePath;
if (!string.IsNullOrEmpty(filePath))
var text = trivia.ToString().AsSpan().TrimStart();
if (!text.StartsWith(hashColon, StringComparison.Ordinal))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It seemed slightly surprising to me, to not dig out the IgnoredDirectiveTrivia here and look at the items on that. Maybe those APIs aren't guaranteed to be available here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good point, will fix, thanks.

@jjonescz
jjonescz merged commit 9735b67 into dotnet:release/10.0.4xx Jun 1, 2026
28 checks passed
@jjonescz
jjonescz deleted the sprint-shebang-analyzer-break branch June 1, 2026 08:39
@jjonescz

jjonescz commented Jun 1, 2026

Copy link
Copy Markdown
Member Author

/backport to release/10.0.3xx

@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0.3xx (link to workflow run)

@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

@jjonescz backporting to release/10.0.3xx failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patch

Applying: File-based apps: ensure shebang analyzer only applies to `#:include`
Using index info to reconstruct a base tree...
M	src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.NetCore.Analyzers/Usage/MissingShebangInFileBasedProgramTests.cs
M	src/Microsoft.DotNet.ProjectTools/VirtualProjectBuilder.cs
A	test/dotnet.Tests/CommandTests/Run/RunFileTests_BuildOptions.cs
A	test/dotnet.Tests/CommandTests/Run/RunFileTests_CscOnlyAndApi.cs
A	test/dotnet.Tests/CommandTests/Run/RunFileTests_Directives.cs
Falling back to patching base and 3-way merge...
Auto-merging src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.NetCore.Analyzers/Usage/MissingShebangInFileBasedProgramTests.cs
Auto-merging src/Microsoft.DotNet.ProjectTools/VirtualProjectBuilder.cs
CONFLICT (modify/delete): test/dotnet.Tests/CommandTests/Run/RunFileTests_BuildOptions.cs deleted in HEAD and modified in File-based apps: ensure shebang analyzer only applies to `#:include`.  Version File-based apps: ensure shebang analyzer only applies to `#:include` of test/dotnet.Tests/CommandTests/Run/RunFileTests_BuildOptions.cs left in tree.
CONFLICT (modify/delete): test/dotnet.Tests/CommandTests/Run/RunFileTests_CscOnlyAndApi.cs deleted in HEAD and modified in File-based apps: ensure shebang analyzer only applies to `#:include`.  Version File-based apps: ensure shebang analyzer only applies to `#:include` of test/dotnet.Tests/CommandTests/Run/RunFileTests_CscOnlyAndApi.cs left in tree.
CONFLICT (modify/delete): test/dotnet.Tests/CommandTests/Run/RunFileTests_Directives.cs deleted in HEAD and modified in File-based apps: ensure shebang analyzer only applies to `#:include`.  Version File-based apps: ensure shebang analyzer only applies to `#:include` of test/dotnet.Tests/CommandTests/Run/RunFileTests_Directives.cs left in tree.
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Patch failed at 0001 File-based apps: ensure shebang analyzer only applies to `#:include`
Error: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-run-file Items related to the "dotnet run <file>" effort

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants