Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Move IsValidEntryPointPath
  • Loading branch information
tmat committed Dec 5, 2025
commit 94296716ecdd75f15d8b6e74ad2f41428e12025e
3 changes: 2 additions & 1 deletion src/Cli/dotnet/Commands/CommandFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Cli.Commands.Run;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.ProjectTools;

namespace Microsoft.DotNet.Cli.Commands;

Expand All @@ -23,7 +24,7 @@ internal static CommandBase CreateVirtualOrPhysicalCommand(
var args = parseResult.GetValue(catchAllUserInputArgument) ?? [];
LoggerUtility.SeparateBinLogArguments(args, out var binLogArgs, out var nonBinLogArgs);
var forwardedArgs = parseResult.OptionValuesToBeForwarded(command);
if (nonBinLogArgs is [{ } arg] && VirtualProjectBuildingCommand.IsValidEntryPointPath(arg))
if (nonBinLogArgs is [{ } arg] && VirtualProjectBuilder.IsValidEntryPointPath(arg))
{
var msbuildArgs = MSBuildArgs.AnalyzeMSBuildArguments([.. forwardedArgs, .. binLogArgs],
[
Expand Down
3 changes: 2 additions & 1 deletion src/Cli/dotnet/Commands/Package/Add/PackageAddCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.FileBasedPrograms;
using NuGet.ProjectModel;
using Microsoft.DotNet.ProjectTools;

namespace Microsoft.DotNet.Cli.Commands.Package.Add;

Expand All @@ -25,7 +26,7 @@ public override int Execute()
{
var (fileOrDirectory, allowedAppKinds) = PackageCommandParser.ProcessPathOptions(_parseResult);

if (allowedAppKinds.HasFlag(AppKinds.FileBased) && VirtualProjectBuildingCommand.IsValidEntryPointPath(fileOrDirectory))
if (allowedAppKinds.HasFlag(AppKinds.FileBased) && VirtualProjectBuilder.IsValidEntryPointPath(fileOrDirectory))
{
return ExecuteForFileBasedApp(fileOrDirectory);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.FileBasedPrograms;
using Microsoft.DotNet.ProjectTools;

namespace Microsoft.DotNet.Cli.Commands.Package.Remove;

Expand All @@ -24,7 +25,7 @@ public override int Execute()

var (fileOrDirectory, allowedAppKinds) = PackageCommandParser.ProcessPathOptions(_parseResult);

if (allowedAppKinds.HasFlag(AppKinds.FileBased) && VirtualProjectBuildingCommand.IsValidEntryPointPath(fileOrDirectory))
if (allowedAppKinds.HasFlag(AppKinds.FileBased) && VirtualProjectBuilder.IsValidEntryPointPath(fileOrDirectory))
{
return ExecuteForFileBasedApp(path: fileOrDirectory, packageId: packageToRemove);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public override int Execute()
{
// Check the entry point file path.
string file = Path.GetFullPath(_file);
if (!VirtualProjectBuildingCommand.IsValidEntryPointPath(file))
if (!VirtualProjectBuilder.IsValidEntryPointPath(file))
{
throw new GracefulException(CliCommandStrings.InvalidFilePath, file);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Cli/dotnet/Commands/Run/RunCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,7 @@ internal static void ThrowUnableToRunError(ProjectInstance project)

if (!readCodeFromStdin)
{
if (VirtualProjectBuildingCommand.IsValidEntryPointPath(arg))
if (VirtualProjectBuilder.IsValidEntryPointPath(arg))
{
arg = Path.GetFullPath(arg);
}
Expand Down
26 changes: 0 additions & 26 deletions src/Cli/dotnet/Commands/Run/VirtualProjectBuildingCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1074,32 +1074,6 @@ public static void RemoveDirectivesFromFile(ImmutableArray<CSharpDirective> dire
}
}

public static bool IsValidEntryPointPath(string entryPointFilePath)
{
if (!File.Exists(entryPointFilePath))
{
return false;
}

if (entryPointFilePath.EndsWith(".cs", StringComparison.OrdinalIgnoreCase))
{
return true;
}

// Check if the first two characters are #!
try
{
using var stream = File.OpenRead(entryPointFilePath);
int first = stream.ReadByte();
int second = stream.ReadByte();
return first == '#' && second == '!';
}
catch
{
return false;
}
}

public static readonly ErrorReporter ThrowingReporter =
static (sourceFile, textSpan, message) => throw new GracefulException($"{sourceFile.GetLocationString(textSpan)}: {FileBasedProgramsResources.DirectiveError}: {message}");
}
Expand Down
3 changes: 2 additions & 1 deletion src/Cli/dotnet/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Cli.Utils.Extensions;
using Microsoft.DotNet.Configurer;
using Microsoft.DotNet.ProjectTools;
using Microsoft.DotNet.Utilities;
using Microsoft.Extensions.EnvironmentAbstractions;
using NuGet.Frameworks;
Expand Down Expand Up @@ -308,7 +309,7 @@ internal static int ProcessArgs(string[] args, TimeSpan startupTime)
// If we didn't match any built-in commands, and a C# file path is the first argument,
// parse as `dotnet run --file file.cs ..rest_of_args` instead.
if (parseResult.GetValue(Parser.DotnetSubCommand) is { } unmatchedCommandOrFile
&& VirtualProjectBuildingCommand.IsValidEntryPointPath(unmatchedCommandOrFile))
&& VirtualProjectBuilder.IsValidEntryPointPath(unmatchedCommandOrFile))
{
List<string> otherTokens = new(parseResult.Tokens.Count - 1);
foreach (var token in parseResult.Tokens)
Expand Down
3 changes: 2 additions & 1 deletion src/Cli/dotnet/ReleasePropertyProjectLocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Microsoft.Build.Execution;
using Microsoft.DotNet.Cli.Commands.Run;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.ProjectTools;
using Microsoft.NET.Build.Tasks;
using Microsoft.VisualStudio.SolutionPersistence.Model;

Expand Down Expand Up @@ -110,7 +111,7 @@ DependentCommandOptions commandOptions
{
foreach (string arg in _slnOrProjectArgs.Append(Directory.GetCurrentDirectory()))
{
if (VirtualProjectBuildingCommand.IsValidEntryPointPath(arg))
if (VirtualProjectBuilder.IsValidEntryPointPath(arg))
{
return new VirtualProjectBuildingCommand(Path.GetFullPath(arg), MSBuildArgs.FromProperties(globalProps))
.CreateProjectInstance(ProjectCollection.GlobalProjectCollection);
Expand Down
26 changes: 26 additions & 0 deletions src/Microsoft.DotNet.ProjectTools/VirtualProjectBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,32 @@ public static string GetTempSubpath(string name)
return Path.Join(GetTempSubdirectory(), name);
}

public static bool IsValidEntryPointPath(string entryPointFilePath)
{
if (!File.Exists(entryPointFilePath))
{
return false;
}

if (entryPointFilePath.EndsWith(".cs", StringComparison.OrdinalIgnoreCase))
{
return true;
}

// Check if the first two characters are #!
try
{
using var stream = File.OpenRead(entryPointFilePath);
int first = stream.ReadByte();
int second = stream.ReadByte();
return first == '#' && second == '!';
}
catch
{
return false;
}
}

/// <summary>
/// If there are any <c>#:project</c> <paramref name="directives"/>, expands <c>$()</c> in them and ensures they point to project files (not directories).
/// </summary>
Expand Down