diff --git a/.editorconfig b/.editorconfig index 1caf766b86fe..cc2382db994b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -170,6 +170,7 @@ file_header_template = Licensed to the .NET Foundation under one or more agreeme dotnet_code_quality.ca1802.api_surface = private, internal dotnet_code_quality.ca1822.api_surface = private, internal dotnet_code_quality.ca2208.api_surface = public +dotnet_public_api_analyzer.require_api_files = true # Mark attributes with AttributeUsageAttribute dotnet_diagnostic.CA1018.severity = warning # Properties should not be write only diff --git a/src/Cli/Microsoft.DotNet.FileBasedPrograms/FileLevelDirectiveHelpers.cs b/src/Cli/Microsoft.DotNet.FileBasedPrograms/FileLevelDirectiveHelpers.cs index 1e4d853c08b2..99e7ba172924 100644 --- a/src/Cli/Microsoft.DotNet.FileBasedPrograms/FileLevelDirectiveHelpers.cs +++ b/src/Cli/Microsoft.DotNet.FileBasedPrograms/FileLevelDirectiveHelpers.cs @@ -36,7 +36,7 @@ public static SyntaxTokenParser CreateTokenizer(SourceText text) /// The latter is useful for dotnet run file.cs where if there are app directives after the first token, /// compiler reports anyway, so we speed up success scenarios by not parsing the whole file up front in the SDK CLI. /// - public static ImmutableArray FindDirectives(SourceFile sourceFile, bool reportAllErrors, ErrorReporter reportError) + public static ImmutableArray FindDirectives(SourceFile sourceFile, bool reportAllErrors, ErrorReporter errorReporter) { var builder = ImmutableArray.CreateBuilder(); var tokenizer = CreateTokenizer(sourceFile.Text); @@ -44,7 +44,7 @@ public static ImmutableArray FindDirectives(SourceFile sourceFi var result = tokenizer.ParseLeadingTrivia(); var triviaList = result.Token.LeadingTrivia; - FindLeadingDirectives(sourceFile, triviaList, reportError, builder); + FindLeadingDirectives(sourceFile, triviaList, errorReporter, builder); // In conversion mode, we want to report errors for any invalid directives in the rest of the file // so users don't end up with invalid directives in the converted project. @@ -73,7 +73,7 @@ void ReportErrorFor(SyntaxTrivia trivia) { if (trivia.ContainsDiagnostics && trivia.IsKind(SyntaxKind.IgnoredDirectiveTrivia)) { - reportError(sourceFile, trivia.Span, FileBasedProgramsResources.CannotConvertDirective); + errorReporter(sourceFile.Text, sourceFile.Path, trivia.Span, FileBasedProgramsResources.CannotConvertDirective); } } @@ -86,7 +86,7 @@ void ReportErrorFor(SyntaxTrivia trivia) public static void FindLeadingDirectives( SourceFile sourceFile, SyntaxTriviaList triviaList, - ErrorReporter reportError, + ErrorReporter errorReporter, ImmutableArray.Builder? builder) { var deduplicated = new Dictionary(NamedDirectiveComparer.Instance); @@ -144,7 +144,7 @@ public static void FindLeadingDirectives( LeadingWhiteSpace = whiteSpace.Leading, TrailingWhiteSpace = whiteSpace.Trailing, }, - ReportError = reportError, + ErrorReporter = errorReporter, DirectiveKind = name, DirectiveText = value, }; @@ -152,7 +152,7 @@ public static void FindLeadingDirectives( // Block quotes now so we can later support quoted values without a breaking change. https://github.com/dotnet/sdk/issues/49367 if (value.Contains('"')) { - reportError(sourceFile, context.Info.Span, FileBasedProgramsResources.QuoteInDirective); + context.ReportError(FileBasedProgramsResources.QuoteInDirective); } if (CSharpDirective.Parse(context) is { } directive) @@ -161,7 +161,7 @@ public static void FindLeadingDirectives( if (deduplicated.TryGetValue(directive, out var existingDirective)) { var typeAndName = $"#:{existingDirective.GetType().Name.ToLowerInvariant()} {existingDirective.Name}"; - reportError(sourceFile, directive.Info.Span, string.Format(FileBasedProgramsResources.DuplicateDirective, typeAndName)); + context.ReportError(directive.Info.Span, string.Format(FileBasedProgramsResources.DuplicateDirective, typeAndName)); } else { @@ -230,16 +230,6 @@ public static SourceFile Load(string filePath) return new SourceFile(filePath, SourceText.From(stream, encoding: null)); } - public SourceFile WithPath(string newPath) - { - return new SourceFile(newPath, Text); - } - - public SourceFile WithText(SourceText newText) - { - return new SourceFile(Path, newText); - } - public void Save() { using var stream = File.Open(Path, FileMode.Create, FileAccess.Write); @@ -249,15 +239,9 @@ public void Save() Text.Write(writer); } - public FileLinePositionSpan GetFileLinePositionSpan(TextSpan span) - { - return new FileLinePositionSpan(Path, Text.Lines.GetLinePositionSpan(span)); - } - public string GetLocationString(TextSpan span) { - var positionSpan = GetFileLinePositionSpan(span); - return $"{positionSpan.Path}({positionSpan.StartLinePosition.Line + 1})"; + return $"{Path}({Text.Lines.GetLinePositionSpan(span).Start.Line + 1})"; } } @@ -298,9 +282,15 @@ public readonly struct ParseInfo public readonly struct ParseContext { public required ParseInfo Info { get; init; } - public required ErrorReporter ReportError { get; init; } + public required ErrorReporter ErrorReporter { get; init; } public required string DirectiveKind { get; init; } public required string DirectiveText { get; init; } + + public void ReportError(string message) + => ErrorReporter(Info.SourceFile.Text, Info.SourceFile.Path, Info.Span, message); + + public void ReportError(TextSpan span, string message) + => ErrorReporter(Info.SourceFile.Text, Info.SourceFile.Path, span, message); } public static Named? Parse(in ParseContext context) @@ -313,7 +303,7 @@ public readonly struct ParseContext case "project": return Project.Parse(context); case "include" or "exclude": return IncludeOrExclude.Parse(context); default: - context.ReportError(context.Info.SourceFile, context.Info.Span, string.Format(FileBasedProgramsResources.UnrecognizedDirective, context.DirectiveKind)); + context.ReportError(string.Format(FileBasedProgramsResources.UnrecognizedDirective, context.DirectiveKind)); return null; } } @@ -326,14 +316,14 @@ private static (string, string?)? ParseOptionalTwoParts(in ParseContext context, string directiveKind = context.DirectiveKind; if (firstPart.IsWhiteSpace()) { - context.ReportError(context.Info.SourceFile, context.Info.Span, string.Format(FileBasedProgramsResources.MissingDirectiveName, directiveKind)); + context.ReportError(string.Format(FileBasedProgramsResources.MissingDirectiveName, directiveKind)); return null; } // If the name contains characters that resemble separators, report an error to avoid any confusion. if (Patterns.DisallowedNameCharacters.Match(context.DirectiveText, beginning: 0, length: firstPart.Length).Success) { - context.ReportError(context.Info.SourceFile, context.Info.Span, string.Format(FileBasedProgramsResources.InvalidDirectiveName, directiveKind, separator)); + context.ReportError(string.Format(FileBasedProgramsResources.InvalidDirectiveName, directiveKind, separator)); return null; } @@ -409,7 +399,7 @@ public sealed class Property(in ParseInfo info) : Named(info) if (propertyValue is null) { - context.ReportError(context.Info.SourceFile, context.Info.Span, FileBasedProgramsResources.PropertyDirectiveMissingParts); + context.ReportError(FileBasedProgramsResources.PropertyDirectiveMissingParts); return null; } @@ -419,14 +409,14 @@ public sealed class Property(in ParseInfo info) : Named(info) } catch (XmlException ex) { - context.ReportError(context.Info.SourceFile, context.Info.Span, string.Format(FileBasedProgramsResources.PropertyDirectiveInvalidName, ex.Message), ex); + context.ReportError(string.Format(FileBasedProgramsResources.PropertyDirectiveInvalidName, ex.Message)); return null; } if (propertyName.Equals("RestoreUseStaticGraphEvaluation", StringComparison.OrdinalIgnoreCase) && MSBuildUtilities.ConvertStringToBool(propertyValue)) { - context.ReportError(context.Info.SourceFile, context.Info.Span, FileBasedProgramsResources.StaticGraphRestoreNotSupported); + context.ReportError(FileBasedProgramsResources.StaticGraphRestoreNotSupported); } return new Property(context.Info) @@ -498,8 +488,7 @@ public Project(in ParseInfo info, string name) : base(info) var directiveText = context.DirectiveText; if (directiveText.IsWhiteSpace()) { - string directiveKind = context.DirectiveKind; - context.ReportError(context.Info.SourceFile, context.Info.Span, string.Format(FileBasedProgramsResources.MissingDirectiveName, directiveKind)); + context.ReportError(string.Format(FileBasedProgramsResources.MissingDirectiveName, context.DirectiveKind)); return null; } @@ -537,14 +526,15 @@ public Project WithName(string name, NameKind kind) /// /// If the directive points to a directory, returns a new directive pointing to the corresponding project file. /// - public Project EnsureProjectFilePath(ErrorReporter reportError) + public Project EnsureProjectFilePath(ErrorReporter errorReporter) { var resolvedName = Name; + var sourcePath = Info.SourceFile.Path; // If the path is a directory like '../lib', transform it to a project file path like '../lib/lib.csproj'. // Also normalize backslashes to forward slashes to ensure the directive works on all platforms. - var sourceDirectory = Path.GetDirectoryName(Info.SourceFile.Path) - ?? throw new InvalidOperationException($"Source file path '{Info.SourceFile.Path}' does not have a containing directory."); + var sourceDirectory = Path.GetDirectoryName(sourcePath) + ?? throw new InvalidOperationException($"Source file path '{sourcePath}' does not have a containing directory."); var resolvedProjectPath = Path.Combine(sourceDirectory, resolvedName.Replace('\\', '/')); if (Directory.Exists(resolvedProjectPath)) @@ -558,16 +548,18 @@ public Project EnsureProjectFilePath(ErrorReporter reportError) } else { - reportError(Info.SourceFile, Info.Span, string.Format(FileBasedProgramsResources.InvalidProjectDirective, error)); + ReportError(string.Format(FileBasedProgramsResources.InvalidProjectDirective, error)); } } else if (!File.Exists(resolvedProjectPath)) { - reportError(Info.SourceFile, Info.Span, - string.Format(FileBasedProgramsResources.InvalidProjectDirective, string.Format(FileBasedProgramsResources.CouldNotFindProjectOrDirectory, resolvedProjectPath))); + ReportError(string.Format(FileBasedProgramsResources.InvalidProjectDirective, string.Format(FileBasedProgramsResources.CouldNotFindProjectOrDirectory, resolvedProjectPath))); } return WithName(resolvedName, NameKind.ProjectFilePath); + + void ReportError(string message) + => errorReporter(Info.SourceFile.Text, sourcePath, Info.Span, message); } public override string ToString() => $"#:project {Name}"; @@ -628,7 +620,7 @@ public sealed class IncludeOrExclude(in ParseInfo info) : Named(info) if (directiveText.IsWhiteSpace()) { string directiveKind = context.DirectiveKind; - context.ReportError(context.Info.SourceFile, context.Info.Span, string.Format(FileBasedProgramsResources.MissingDirectiveName, directiveKind)); + context.ReportError(string.Format(FileBasedProgramsResources.MissingDirectiveName, directiveKind)); return null; } @@ -659,7 +651,7 @@ public IncludeOrExclude WithDeterminedItemType(ErrorReporter reportError, Immuta if (itemType is null) { - reportError(Info.SourceFile, Info.Span, + reportError(Info.SourceFile.Text, Info.SourceFile.Path, Info.Span, string.Format(FileBasedProgramsResources.IncludeOrExcludeDirectiveUnknownFileType, $"#:{KindToString()}", string.Join(", ", mapping.Select(static e => e.Extension)))); @@ -730,7 +722,7 @@ public string KindToMSBuildString() public static ImmutableArray<(string Extension, string ItemType)> ParseMapping( string value, SourceFile sourceFile, - ErrorReporter reportError) + ErrorReporter errorReporter) { var pairs = value.Split(';'); @@ -742,7 +734,7 @@ public string KindToMSBuildString() if (parts.Length != 2) { - reportError(sourceFile, default, string.Format(FileBasedProgramsResources.InvalidIncludeExcludeMappingEntry, pair)); + ReportError(string.Format(FileBasedProgramsResources.InvalidIncludeExcludeMappingEntry, pair)); continue; } @@ -751,13 +743,13 @@ public string KindToMSBuildString() if (extension is not ['.', _, ..]) { - reportError(sourceFile, default, string.Format(FileBasedProgramsResources.InvalidIncludeExcludeMappingExtension, extension, pair)); + ReportError(string.Format(FileBasedProgramsResources.InvalidIncludeExcludeMappingExtension, extension, pair)); continue; } if (itemType.IsWhiteSpace()) { - reportError(sourceFile, default, string.Format(FileBasedProgramsResources.InvalidIncludeExcludeMappingItemType, itemType, pair)); + ReportError(string.Format(FileBasedProgramsResources.InvalidIncludeExcludeMappingItemType, itemType, pair)); continue; } @@ -765,6 +757,9 @@ public string KindToMSBuildString() } return builder.DrainToImmutable(); + + void ReportError(string message) + => errorReporter(sourceFile.Text, sourceFile.Path, default, message); } } } @@ -817,25 +812,25 @@ public readonly struct Position } } -internal delegate void ErrorReporter(SourceFile sourceFile, TextSpan textSpan, string message, Exception? innerException = null); +internal delegate void ErrorReporter(SourceText text, string path, TextSpan textSpan, string message, Exception? innerException = null); internal static partial class ErrorReporters { public static readonly ErrorReporter IgnoringReporter = - static (_, _, _, _) => { }; + static (_, _, _, _, _) => { }; public static ErrorReporter CreateCollectingReporter(out ImmutableArray.Builder builder) { var capturedBuilder = builder = ImmutableArray.CreateBuilder(); - return (sourceFile, textSpan, message, _) => + return (text, path, textSpan, message, _) => capturedBuilder.Add(new SimpleDiagnostic { Location = new SimpleDiagnostic.Position() { - Path = sourceFile.Path, + Path = path, TextSpan = textSpan, - Span = sourceFile.GetFileLinePositionSpan(textSpan).Span + Span = text.Lines.GetLinePositionSpan(textSpan) }, Message = message }); diff --git a/src/Cli/Microsoft.DotNet.FileBasedPrograms/InternalAPI.Unshipped.txt b/src/Cli/Microsoft.DotNet.FileBasedPrograms/InternalAPI.Unshipped.txt index 74c5d7f313bb..df17c8e67fc1 100644 --- a/src/Cli/Microsoft.DotNet.FileBasedPrograms/InternalAPI.Unshipped.txt +++ b/src/Cli/Microsoft.DotNet.FileBasedPrograms/InternalAPI.Unshipped.txt @@ -34,11 +34,13 @@ Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseContext.DirectiveKind.ge Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseContext.DirectiveKind.init -> void Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseContext.DirectiveText.get -> string! Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseContext.DirectiveText.init -> void +Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseContext.ErrorReporter.get -> Microsoft.DotNet.FileBasedPrograms.ErrorReporter! +Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseContext.ErrorReporter.init -> void Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseContext.Info.get -> Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseInfo Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseContext.Info.init -> void Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseContext.ParseContext() -> void -Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseContext.ReportError.get -> Microsoft.DotNet.FileBasedPrograms.ErrorReporter! -Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseContext.ReportError.init -> void +Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseContext.ReportError(Microsoft.CodeAnalysis.Text.TextSpan span, string! message) -> void +Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseContext.ReportError(string! message) -> void Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseContext.SourceFile.get -> Microsoft.DotNet.FileBasedPrograms.SourceFile Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseContext.SourceFile.init -> void Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseInfo @@ -52,7 +54,7 @@ Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseInfo.Span.init -> void Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseInfo.TrailingWhiteSpace.get -> Microsoft.DotNet.FileBasedPrograms.WhiteSpaceInfo Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseInfo.TrailingWhiteSpace.init -> void Microsoft.DotNet.FileBasedPrograms.CSharpDirective.Project -Microsoft.DotNet.FileBasedPrograms.CSharpDirective.Project.EnsureProjectFilePath(Microsoft.DotNet.FileBasedPrograms.ErrorReporter! reportError) -> Microsoft.DotNet.FileBasedPrograms.CSharpDirective.Project! +Microsoft.DotNet.FileBasedPrograms.CSharpDirective.Project.EnsureProjectFilePath(Microsoft.DotNet.FileBasedPrograms.ErrorReporter! errorReporter) -> Microsoft.DotNet.FileBasedPrograms.CSharpDirective.Project! Microsoft.DotNet.FileBasedPrograms.CSharpDirective.Project.ExpandedName.get -> string? Microsoft.DotNet.FileBasedPrograms.CSharpDirective.Project.ExpandedName.init -> void Microsoft.DotNet.FileBasedPrograms.CSharpDirective.Project.NameKind @@ -103,7 +105,6 @@ Microsoft.DotNet.FileBasedPrograms.SimpleDiagnostic.SimpleDiagnostic() -> void Microsoft.DotNet.FileBasedPrograms.SourceFile Microsoft.DotNet.FileBasedPrograms.SourceFile.Deconstruct(out string! Path, out Microsoft.CodeAnalysis.Text.SourceText! Text) -> void Microsoft.DotNet.FileBasedPrograms.SourceFile.Equals(Microsoft.DotNet.FileBasedPrograms.SourceFile other) -> bool -Microsoft.DotNet.FileBasedPrograms.SourceFile.GetFileLinePositionSpan(Microsoft.CodeAnalysis.Text.TextSpan span) -> Microsoft.CodeAnalysis.FileLinePositionSpan Microsoft.DotNet.FileBasedPrograms.SourceFile.GetLocationString(Microsoft.CodeAnalysis.Text.TextSpan span) -> string! Microsoft.DotNet.FileBasedPrograms.SourceFile.Path.get -> string! Microsoft.DotNet.FileBasedPrograms.SourceFile.Path.init -> void @@ -112,8 +113,6 @@ Microsoft.DotNet.FileBasedPrograms.SourceFile.SourceFile() -> void Microsoft.DotNet.FileBasedPrograms.SourceFile.SourceFile(string! Path, Microsoft.CodeAnalysis.Text.SourceText! Text) -> void Microsoft.DotNet.FileBasedPrograms.SourceFile.Text.get -> Microsoft.CodeAnalysis.Text.SourceText! Microsoft.DotNet.FileBasedPrograms.SourceFile.Text.init -> void -Microsoft.DotNet.FileBasedPrograms.SourceFile.WithPath(string! newPath) -> Microsoft.DotNet.FileBasedPrograms.SourceFile -Microsoft.DotNet.FileBasedPrograms.SourceFile.WithText(Microsoft.CodeAnalysis.Text.SourceText! newText) -> Microsoft.DotNet.FileBasedPrograms.SourceFile Microsoft.DotNet.FileBasedPrograms.WhiteSpaceInfo Microsoft.DotNet.FileBasedPrograms.WhiteSpaceInfo.LineBreaks -> int Microsoft.DotNet.FileBasedPrograms.WhiteSpaceInfo.TotalLength -> int @@ -130,7 +129,7 @@ override Microsoft.DotNet.FileBasedPrograms.SourceFile.GetHashCode() -> int static Microsoft.DotNet.FileBasedPrograms.CSharpDirective.IncludeOrExclude.DefaultMapping.get -> System.Collections.Immutable.ImmutableArray<(string! Extension, string! ItemType)> static Microsoft.DotNet.FileBasedPrograms.CSharpDirective.IncludeOrExclude.DefaultMappingString.get -> string! static Microsoft.DotNet.FileBasedPrograms.CSharpDirective.IncludeOrExclude.Parse(in Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseContext context) -> Microsoft.DotNet.FileBasedPrograms.CSharpDirective.IncludeOrExclude? -static Microsoft.DotNet.FileBasedPrograms.CSharpDirective.IncludeOrExclude.ParseMapping(string! value, Microsoft.DotNet.FileBasedPrograms.SourceFile sourceFile, Microsoft.DotNet.FileBasedPrograms.ErrorReporter! reportError) -> System.Collections.Immutable.ImmutableArray<(string! Extension, string! ItemType)> +static Microsoft.DotNet.FileBasedPrograms.CSharpDirective.IncludeOrExclude.ParseMapping(string! value, Microsoft.DotNet.FileBasedPrograms.SourceFile sourceFile, Microsoft.DotNet.FileBasedPrograms.ErrorReporter! errorReporter) -> System.Collections.Immutable.ImmutableArray<(string! Extension, string! ItemType)> static Microsoft.DotNet.FileBasedPrograms.CSharpDirective.Package.Parse(in Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseContext context) -> Microsoft.DotNet.FileBasedPrograms.CSharpDirective.Package? static Microsoft.DotNet.FileBasedPrograms.CSharpDirective.Parse(in Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseContext context) -> Microsoft.DotNet.FileBasedPrograms.CSharpDirective.Named? static Microsoft.DotNet.FileBasedPrograms.CSharpDirective.Project.Parse(in Microsoft.DotNet.FileBasedPrograms.CSharpDirective.ParseContext context) -> Microsoft.DotNet.FileBasedPrograms.CSharpDirective.Project? @@ -141,9 +140,8 @@ static Microsoft.DotNet.FileBasedPrograms.ExternalHelpers.CombineHashCodes(int v static Microsoft.DotNet.FileBasedPrograms.ExternalHelpers.GetRelativePath(string! relativeTo, string! path) -> string! static Microsoft.DotNet.FileBasedPrograms.ExternalHelpers.IsPathFullyQualified(string! path) -> bool static Microsoft.DotNet.FileBasedPrograms.FileLevelDirectiveHelpers.CreateTokenizer(Microsoft.CodeAnalysis.Text.SourceText! text) -> Microsoft.CodeAnalysis.CSharp.SyntaxTokenParser! -static Microsoft.DotNet.FileBasedPrograms.FileLevelDirectiveHelpers.EvaluateDirectives(Microsoft.Build.Execution.ProjectInstance? project, System.Collections.Immutable.ImmutableArray directives, Microsoft.DotNet.FileBasedPrograms.SourceFile sourceFile, Microsoft.DotNet.FileBasedPrograms.ErrorReporter! errorReporter) -> System.Collections.Immutable.ImmutableArray -static Microsoft.DotNet.FileBasedPrograms.FileLevelDirectiveHelpers.FindDirectives(Microsoft.DotNet.FileBasedPrograms.SourceFile sourceFile, bool reportAllErrors, Microsoft.DotNet.FileBasedPrograms.ErrorReporter! reportError) -> System.Collections.Immutable.ImmutableArray -static Microsoft.DotNet.FileBasedPrograms.FileLevelDirectiveHelpers.FindLeadingDirectives(Microsoft.DotNet.FileBasedPrograms.SourceFile sourceFile, Microsoft.CodeAnalysis.SyntaxTriviaList triviaList, Microsoft.DotNet.FileBasedPrograms.ErrorReporter! reportError, System.Collections.Immutable.ImmutableArray.Builder? builder) -> void +static Microsoft.DotNet.FileBasedPrograms.FileLevelDirectiveHelpers.FindDirectives(Microsoft.DotNet.FileBasedPrograms.SourceFile sourceFile, bool reportAllErrors, Microsoft.DotNet.FileBasedPrograms.ErrorReporter! errorReporter) -> System.Collections.Immutable.ImmutableArray +static Microsoft.DotNet.FileBasedPrograms.FileLevelDirectiveHelpers.FindLeadingDirectives(Microsoft.DotNet.FileBasedPrograms.SourceFile sourceFile, Microsoft.CodeAnalysis.SyntaxTriviaList triviaList, Microsoft.DotNet.FileBasedPrograms.ErrorReporter! errorReporter, System.Collections.Immutable.ImmutableArray.Builder? builder) -> void static Microsoft.DotNet.FileBasedPrograms.MSBuildUtilities.ConvertStringToBool(string? parameterValue, bool defaultValue = false) -> bool static Microsoft.DotNet.FileBasedPrograms.Patterns.DisallowedNameCharacters.get -> System.Text.RegularExpressions.Regex! static Microsoft.DotNet.FileBasedPrograms.Patterns.EscapedCompilerOption.get -> System.Text.RegularExpressions.Regex! @@ -154,6 +152,6 @@ static Microsoft.DotNet.FileBasedPrograms.SourceFile.operator ==(Microsoft.DotNe static Microsoft.DotNet.ProjectTools.ProjectLocator.TryGetProjectFileFromDirectory(string! projectDirectory, out string? projectFilePath, out string? error) -> bool static readonly Microsoft.DotNet.FileBasedPrograms.ErrorReporters.IgnoringReporter -> Microsoft.DotNet.FileBasedPrograms.ErrorReporter! static readonly Microsoft.DotNet.FileBasedPrograms.NamedDirectiveComparer.Instance -> Microsoft.DotNet.FileBasedPrograms.NamedDirectiveComparer! -virtual Microsoft.DotNet.FileBasedPrograms.ErrorReporter.Invoke(Microsoft.DotNet.FileBasedPrograms.SourceFile sourceFile, Microsoft.CodeAnalysis.Text.TextSpan textSpan, string! message, System.Exception? innerException = null) -> void +virtual Microsoft.DotNet.FileBasedPrograms.ErrorReporter.Invoke(Microsoft.CodeAnalysis.Text.SourceText! text, string! path, Microsoft.CodeAnalysis.Text.TextSpan textSpan, string! message, System.Exception? innerException = null) -> void ~override Microsoft.DotNet.FileBasedPrograms.SourceFile.Equals(object obj) -> bool ~override Microsoft.DotNet.FileBasedPrograms.SourceFile.ToString() -> string \ No newline at end of file diff --git a/src/Cli/dotnet/Commands/Project/Convert/ProjectConvertCommand.cs b/src/Cli/dotnet/Commands/Project/Convert/ProjectConvertCommand.cs index 3a7256ef34d3..4cf768909127 100644 --- a/src/Cli/dotnet/Commands/Project/Convert/ProjectConvertCommand.cs +++ b/src/Cli/dotnet/Commands/Project/Convert/ProjectConvertCommand.cs @@ -43,7 +43,7 @@ public override int Execute() // Create a project instance for evaluation. var projectCollection = new ProjectCollection(); - var builder = new VirtualProjectBuilder(file, VirtualProjectBuildingCommand.TargetFrameworkVersion); + var builder = new VirtualProjectBuilder(file, VirtualProjectBuildingCommand.TargetFramework); builder.CreateProjectInstance( projectCollection, @@ -276,7 +276,7 @@ ImmutableArray UpdateDirectives(ImmutableArray IEnumerable<(string name, string value)> GetDefaultProperties() { - foreach (var (name, defaultValue) in VirtualProjectBuilder.GetDefaultProperties(VirtualProjectBuildingCommand.TargetFrameworkVersion)) + foreach (var (name, defaultValue) in VirtualProjectBuilder.GetDefaultProperties(VirtualProjectBuildingCommand.TargetFramework)) { string projectValue = projectInstance.GetPropertyValue(name); if (string.Equals(projectValue, defaultValue, StringComparison.OrdinalIgnoreCase)) diff --git a/src/Cli/dotnet/Commands/Run/Api/RunApiCommand.cs b/src/Cli/dotnet/Commands/Run/Api/RunApiCommand.cs index 75a333573d09..8960eabd51cc 100644 --- a/src/Cli/dotnet/Commands/Run/Api/RunApiCommand.cs +++ b/src/Cli/dotnet/Commands/Run/Api/RunApiCommand.cs @@ -67,7 +67,7 @@ public override RunApiOutput Execute() { var builder = new VirtualProjectBuilder( entryPointFileFullPath: EntryPointFileFullPath, - targetFrameworkVersion: VirtualProjectBuildingCommand.TargetFrameworkVersion, + targetFramework: VirtualProjectBuildingCommand.TargetFramework, artifactsPath: ArtifactsPath); var errorReporter = ErrorReporters.CreateCollectingReporter(out var diagnostics); @@ -83,7 +83,7 @@ public override RunApiOutput Execute() VirtualProjectBuilder.WriteProjectFile( csprojWriter, evaluatedDirectives, - VirtualProjectBuilder.GetDefaultProperties(VirtualProjectBuildingCommand.TargetFrameworkVersion), + VirtualProjectBuilder.GetDefaultProperties(VirtualProjectBuildingCommand.TargetFramework), isVirtualProject: true, entryPointFilePath: EntryPointFileFullPath, artifactsPath: builder.ArtifactsPath); diff --git a/src/Cli/dotnet/Commands/Run/FileBasedAppSourceEditor.cs b/src/Cli/dotnet/Commands/Run/FileBasedAppSourceEditor.cs index 27ac23b56687..764aeec88f95 100644 --- a/src/Cli/dotnet/Commands/Run/FileBasedAppSourceEditor.cs +++ b/src/Cli/dotnet/Commands/Run/FileBasedAppSourceEditor.cs @@ -80,7 +80,7 @@ static string GetNewLine(SourceText text) public void Add(CSharpDirective directive) { var change = DetermineAddChange(directive); - SourceFile = SourceFile.WithText(SourceFile.Text.WithChanges([change])); + SourceFile = SourceFile with { Text = SourceFile.Text.WithChanges([change]) }; } private TextChange DetermineAddChange(CSharpDirective directive) @@ -231,7 +231,7 @@ public void Remove(CSharpDirective directive) var span = directive.Info.Span; var start = span.Start; var length = span.Length + DetermineTrailingLengthToRemove(directive); - SourceFile = SourceFile.WithText(SourceFile.Text.Replace(start: start, length: length, newText: string.Empty)); + SourceFile = SourceFile with { Text = SourceFile.Text.Replace(start: start, length: length, newText: string.Empty) }; } private static int DetermineTrailingLengthToRemove(CSharpDirective directive) diff --git a/src/Cli/dotnet/Commands/Run/VirtualProjectBuildingCommand.cs b/src/Cli/dotnet/Commands/Run/VirtualProjectBuildingCommand.cs index 25c047e8f53b..3cbd7b9bd1e8 100644 --- a/src/Cli/dotnet/Commands/Run/VirtualProjectBuildingCommand.cs +++ b/src/Cli/dotnet/Commands/Run/VirtualProjectBuildingCommand.cs @@ -83,6 +83,7 @@ internal sealed class VirtualProjectBuildingCommand : CommandBase ]; public static string TargetFrameworkVersion => Product.TargetFrameworkVersion; + public static string TargetFramework => $"net{Product.TargetFrameworkVersion}"; public bool NoRestore { get; init; } @@ -151,7 +152,7 @@ public VirtualProjectBuildingCommand( } .AsReadOnly()); - Builder = new VirtualProjectBuilder(entryPointFileFullPath, TargetFrameworkVersion, MSBuildArgs.GetResolvedTargets(), artifactsPath); + Builder = new VirtualProjectBuilder(entryPointFileFullPath, TargetFramework, MSBuildArgs.GetResolvedTargets(), artifactsPath); } public override int Execute() @@ -1175,8 +1176,9 @@ public static void CreateTempSubdirectory(string path) } public static readonly ErrorReporter ThrowingReporter = - static (sourceFile, textSpan, message, innerException) => throw new GracefulException( - $"{sourceFile.GetLocationString(textSpan)}: {FileBasedProgramsResources.DirectiveError}: {message}", + static (text, path, textSpan, message, innerException) => + throw new GracefulException( + $"{new SourceFile(path, text).GetLocationString(textSpan)}: {FileBasedProgramsResources.DirectiveError}: {message}", innerException); } diff --git a/src/Microsoft.DotNet.ProjectTools/LaunchSettings/ExecutableLaunchProfile.cs b/src/Microsoft.DotNet.ProjectTools/LaunchSettings/ExecutableLaunchProfile.cs index 67db2e0b93ce..e5b000fe50a8 100644 --- a/src/Microsoft.DotNet.ProjectTools/LaunchSettings/ExecutableLaunchProfile.cs +++ b/src/Microsoft.DotNet.ProjectTools/LaunchSettings/ExecutableLaunchProfile.cs @@ -5,7 +5,7 @@ namespace Microsoft.DotNet.ProjectTools; -public sealed class ExecutableLaunchProfile : LaunchProfile +internal sealed class ExecutableLaunchProfile : LaunchProfile { public const string WorkingDirectoryPropertyName = "workingDirectory"; public const string ExecutablePathPropertyName = "executablePath"; diff --git a/src/Microsoft.DotNet.ProjectTools/LaunchSettings/LaunchProfile.cs b/src/Microsoft.DotNet.ProjectTools/LaunchSettings/LaunchProfile.cs index 87f6275e83b3..e994f6635cd7 100644 --- a/src/Microsoft.DotNet.ProjectTools/LaunchSettings/LaunchProfile.cs +++ b/src/Microsoft.DotNet.ProjectTools/LaunchSettings/LaunchProfile.cs @@ -6,7 +6,7 @@ namespace Microsoft.DotNet.ProjectTools; -public abstract class LaunchProfile +internal abstract class LaunchProfile { [JsonIgnore] public string? LaunchProfileName { get; init; } diff --git a/src/Microsoft.DotNet.ProjectTools/LaunchSettings/LaunchProfileParseResult.cs b/src/Microsoft.DotNet.ProjectTools/LaunchSettings/LaunchProfileParseResult.cs index bf735a81cf0a..7bc2e979e3b9 100644 --- a/src/Microsoft.DotNet.ProjectTools/LaunchSettings/LaunchProfileParseResult.cs +++ b/src/Microsoft.DotNet.ProjectTools/LaunchSettings/LaunchProfileParseResult.cs @@ -5,7 +5,7 @@ namespace Microsoft.DotNet.ProjectTools; -public sealed class LaunchProfileParseResult +internal sealed class LaunchProfileParseResult { public string? FailureReason { get; } diff --git a/src/Microsoft.DotNet.ProjectTools/LaunchSettings/LaunchSettings.cs b/src/Microsoft.DotNet.ProjectTools/LaunchSettings/LaunchSettings.cs index ae1c60161b27..e2f9725f18fd 100644 --- a/src/Microsoft.DotNet.ProjectTools/LaunchSettings/LaunchSettings.cs +++ b/src/Microsoft.DotNet.ProjectTools/LaunchSettings/LaunchSettings.cs @@ -18,12 +18,12 @@ public static class LaunchSettings { ExecutableLaunchProfileParser.CommandName, ExecutableLaunchProfileParser.Instance } }; - public static IEnumerable SupportedProfileTypes => s_providers.Keys; + internal static IEnumerable SupportedProfileTypes => s_providers.Keys; - public static string GetPropertiesLaunchSettingsPath(string directoryPath, string propertiesDirectoryName) + internal static string GetPropertiesLaunchSettingsPath(string directoryPath, string propertiesDirectoryName) => Path.Combine(directoryPath, propertiesDirectoryName, "launchSettings.json"); - public static string GetFlatLaunchSettingsPath(string directoryPath, string projectNameWithoutExtension) + internal static string GetFlatLaunchSettingsPath(string directoryPath, string projectNameWithoutExtension) => Path.Join(directoryPath, $"{projectNameWithoutExtension}.run.json"); public static string? TryFindLaunchSettingsFile(string projectOrEntryPointFilePath, string? launchProfile, Action report) @@ -71,7 +71,7 @@ public static string GetFlatLaunchSettingsPath(string directoryPath, string proj return null; } - public static LaunchProfileParseResult ReadProfileSettingsFromFile(string launchSettingsPath, string? profileName = null) + internal static LaunchProfileParseResult ReadProfileSettingsFromFile(string launchSettingsPath, string? profileName = null) { try { diff --git a/src/Microsoft.DotNet.ProjectTools/LaunchSettings/ProjectLaunchProfile.cs b/src/Microsoft.DotNet.ProjectTools/LaunchSettings/ProjectLaunchProfile.cs index a107dc29db84..d131b1f5c29d 100644 --- a/src/Microsoft.DotNet.ProjectTools/LaunchSettings/ProjectLaunchProfile.cs +++ b/src/Microsoft.DotNet.ProjectTools/LaunchSettings/ProjectLaunchProfile.cs @@ -5,7 +5,7 @@ namespace Microsoft.DotNet.ProjectTools; -public sealed class ProjectLaunchProfile : LaunchProfile +internal sealed class ProjectLaunchProfile : LaunchProfile { [JsonPropertyName("launchBrowser")] public bool LaunchBrowser { get; init; } diff --git a/src/Microsoft.DotNet.ProjectTools/Microsoft.DotNet.ProjectTools.csproj b/src/Microsoft.DotNet.ProjectTools/Microsoft.DotNet.ProjectTools.csproj index 9de97043c331..ecea66d30440 100644 --- a/src/Microsoft.DotNet.ProjectTools/Microsoft.DotNet.ProjectTools.csproj +++ b/src/Microsoft.DotNet.ProjectTools/Microsoft.DotNet.ProjectTools.csproj @@ -12,14 +12,21 @@ - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - + + + diff --git a/src/Microsoft.DotNet.ProjectTools/PublicAPI.Shipped.txt b/src/Microsoft.DotNet.ProjectTools/PublicAPI.Shipped.txt new file mode 100644 index 000000000000..7dc5c58110bf --- /dev/null +++ b/src/Microsoft.DotNet.ProjectTools/PublicAPI.Shipped.txt @@ -0,0 +1 @@ +#nullable enable diff --git a/src/Microsoft.DotNet.ProjectTools/PublicAPI.Unshipped.txt b/src/Microsoft.DotNet.ProjectTools/PublicAPI.Unshipped.txt new file mode 100644 index 000000000000..e22fc3a5db63 --- /dev/null +++ b/src/Microsoft.DotNet.ProjectTools/PublicAPI.Unshipped.txt @@ -0,0 +1,6 @@ +#nullable enable +Microsoft.DotNet.ProjectTools.LaunchSettings +Microsoft.DotNet.ProjectTools.VirtualProjectBuilder +static Microsoft.DotNet.ProjectTools.LaunchSettings.TryFindLaunchSettingsFile(string! projectOrEntryPointFilePath, string? launchProfile, System.Action! report) -> string? +static Microsoft.DotNet.ProjectTools.VirtualProjectBuilder.GetVirtualProjectPath(string! entryPointFilePath) -> string! +static Microsoft.DotNet.ProjectTools.VirtualProjectBuilder.IsValidEntryPointPath(string! entryPointFilePath) -> bool diff --git a/src/Microsoft.DotNet.ProjectTools/Utilities/Sha256Hasher.cs b/src/Microsoft.DotNet.ProjectTools/Utilities/Sha256Hasher.cs index 176173e776c5..7a7941e02a39 100644 --- a/src/Microsoft.DotNet.ProjectTools/Utilities/Sha256Hasher.cs +++ b/src/Microsoft.DotNet.ProjectTools/Utilities/Sha256Hasher.cs @@ -5,7 +5,7 @@ namespace Microsoft.DotNet.Utilities; -public static class Sha256Hasher +internal static class Sha256Hasher { /// /// The hashed mac address needs to be the same hashed value as produced by the other distinct sources given the same input. (e.g. VsCode) diff --git a/src/Microsoft.DotNet.ProjectTools/VirtualProjectBuilder.cs b/src/Microsoft.DotNet.ProjectTools/VirtualProjectBuilder.cs index 146947972766..0245bef68abc 100644 --- a/src/Microsoft.DotNet.ProjectTools/VirtualProjectBuilder.cs +++ b/src/Microsoft.DotNet.ProjectTools/VirtualProjectBuilder.cs @@ -15,15 +15,15 @@ namespace Microsoft.DotNet.ProjectTools; -internal sealed class VirtualProjectBuilder +public sealed class VirtualProjectBuilder { private readonly IEnumerable<(string name, string value)> _defaultProperties; private (ImmutableArray Original, ImmutableArray Evaluated)? _evaluatedDirectives; - public string EntryPointFileFullPath { get; } + internal string EntryPointFileFullPath { get; } - public SourceFile EntryPointSourceFile + internal SourceFile EntryPointSourceFile { get { @@ -36,14 +36,14 @@ public SourceFile EntryPointSourceFile } } - public string ArtifactsPath + internal string ArtifactsPath => field ??= GetArtifactsPath(EntryPointFileFullPath); - public string[]? RequestedTargets { get; } + internal string[]? RequestedTargets { get; } - public VirtualProjectBuilder( + internal VirtualProjectBuilder( string entryPointFileFullPath, - string targetFrameworkVersion, + string targetFramework, string[]? requestedTargets = null, string? artifactsPath = null, SourceText? sourceText = null) @@ -53,7 +53,7 @@ public VirtualProjectBuilder( EntryPointFileFullPath = entryPointFileFullPath; RequestedTargets = requestedTargets; ArtifactsPath = artifactsPath; - _defaultProperties = GetDefaultProperties(targetFrameworkVersion); + _defaultProperties = GetDefaultProperties(targetFramework); if (sourceText != null) { @@ -64,17 +64,17 @@ public VirtualProjectBuilder( /// /// Kept in sync with the default dotnet new console project file (enforced by DotnetProjectConvertTests.SameAsTemplate). /// - public static IEnumerable<(string name, string value)> GetDefaultProperties(string targetFrameworkVersion) => + internal static IEnumerable<(string name, string value)> GetDefaultProperties(string targetFramework) => [ ("OutputType", "Exe"), - ("TargetFramework", $"net{targetFrameworkVersion}"), + ("TargetFramework", targetFramework), ("ImplicitUsings", "enable"), ("Nullable", "enable"), ("PublishAot", "true"), ("PackAsTool", "true"), ]; - public static string GetArtifactsPath(string entryPointFileFullPath) + internal static string GetArtifactsPath(string entryPointFileFullPath) { // Include entry point file name so the directory name is not completely opaque. string fileName = Path.GetFileNameWithoutExtension(entryPointFileFullPath); @@ -84,10 +84,13 @@ public static string GetArtifactsPath(string entryPointFileFullPath) return GetTempSubpath(directoryName); } + public static string GetVirtualProjectPath(string entryPointFilePath) + => Path.ChangeExtension(entryPointFilePath, ".csproj"); + /// /// Obtains a temporary subdirectory for file-based app artifacts, e.g., /tmp/dotnet/runfile/. /// - public static string GetTempSubdirectory() + internal static string GetTempSubdirectory() { // We want a location where permissions are expected to be restricted to the current user. string directory = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) @@ -105,7 +108,7 @@ public static string GetTempSubdirectory() /// /// Obtains a specific temporary path in a subdirectory for file-based app artifacts, e.g., /tmp/dotnet/runfile/{name}. /// - public static string GetTempSubpath(string name) + internal static string GetTempSubpath(string name) { return Path.Join(GetTempSubdirectory(), name); } @@ -198,7 +201,7 @@ private ImmutableArray EvaluateDirectives( return builder.DrainToImmutable(); } - public ImmutableArray<(string Extension, string ItemType)> GetItemMapping(ProjectInstance project, ErrorReporter reportError) + internal ImmutableArray<(string Extension, string ItemType)> GetItemMapping(ProjectInstance project, ErrorReporter reportError) { return MSBuildUtilities.ConvertStringToBool(project.GetPropertyValue(CSharpDirective.IncludeOrExclude.ExperimentalFileBasedProgramEnableItemMapping)) ? CSharpDirective.IncludeOrExclude.ParseMapping( @@ -208,7 +211,7 @@ private ImmutableArray EvaluateDirectives( : CSharpDirective.IncludeOrExclude.DefaultMapping; } - public void CreateProjectInstance( + internal void CreateProjectInstance( ProjectCollection projectCollection, ErrorReporter reportError, out ProjectInstance project, @@ -295,7 +298,7 @@ bool TryGetNextFileToProcess() { if (!File.Exists(filePath)) { - reportError(EntryPointSourceFile, default, string.Format(Resources.IncludedFileNotFound, filePath)); + reportError(EntryPointSourceFile.Text, EntryPointSourceFile.Path, default, string.Format(Resources.IncludedFileNotFound, filePath)); continue; } @@ -398,14 +401,15 @@ void CheckFlagEnabled(ref bool? flag, string flagName, CSharpDirective directive if (!value) { reportError( - directive.Info.SourceFile, + directive.Info.SourceFile.Text, + directive.Info.SourceFile.Path, directive.Info.Span, string.Format(Resources.ExperimentalFeatureDisabled, flagName)); } } } - public static void WriteProjectFile( + internal static void WriteProjectFile( TextWriter writer, ImmutableArray directives, IEnumerable<(string name, string value)> defaultProperties, @@ -754,7 +758,7 @@ static void WriteImport(TextWriter writer, string project, CSharpDirective.Sdk s } } - public static SourceFile RemoveDirectivesFromFile(ImmutableArray directives, SourceFile sourceFile) + internal static SourceFile RemoveDirectivesFromFile(ImmutableArray directives, SourceFile sourceFile) { if (directives.Length == 0) { @@ -779,12 +783,12 @@ public static SourceFile RemoveDirectivesFromFile(ImmutableArray directives, SourceFile sourceFile, string targetFilePath) + internal static void RemoveDirectivesFromFile(ImmutableArray directives, SourceFile sourceFile, string targetFilePath) { var modifiedFile = RemoveDirectivesFromFile(directives, sourceFile); - modifiedFile.WithPath(targetFilePath).Save(); + (modifiedFile with { Path = targetFilePath }).Save(); } } diff --git a/test/dotnet.Tests/CommandTests/Project/Convert/DotnetProjectConvertTests.cs b/test/dotnet.Tests/CommandTests/Project/Convert/DotnetProjectConvertTests.cs index 87a1e4100431..b379f8eee8bb 100644 --- a/test/dotnet.Tests/CommandTests/Project/Convert/DotnetProjectConvertTests.cs +++ b/test/dotnet.Tests/CommandTests/Project/Convert/DotnetProjectConvertTests.cs @@ -1937,7 +1937,7 @@ private static void Convert( { var builder = new VirtualProjectBuilder( entryPointFileFullPath: filePath, - targetFrameworkVersion: VirtualProjectBuildingCommand.TargetFrameworkVersion, + targetFramework: VirtualProjectBuildingCommand.TargetFramework, sourceText: SourceText.From(inputCSharp, Encoding.UTF8)); var errorReporter = ErrorReporters.CreateCollectingReporter(out actualDiagnostics); @@ -1963,7 +1963,7 @@ private static void Convert( VirtualProjectBuilder.WriteProjectFile( projectWriter, directives, - VirtualProjectBuilder.GetDefaultProperties(VirtualProjectBuildingCommand.TargetFrameworkVersion), + VirtualProjectBuilder.GetDefaultProperties(VirtualProjectBuildingCommand.TargetFramework), isVirtualProject: false); actualProject = projectWriter.ToString(); diff --git a/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs b/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs index 732de1dde6b2..c908a7142cf2 100644 --- a/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs +++ b/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs @@ -5,6 +5,7 @@ using System.Runtime.Versioning; using System.Text.Json; using Basic.CompilerLog.Util; +using Microsoft.Build.Evaluation; using Microsoft.Build.Framework; using Microsoft.Build.Logging.StructuredLogger; using Microsoft.CodeAnalysis; @@ -3808,7 +3809,7 @@ public void IncludeDirective_CustomMapping_Api() var builder = new VirtualProjectBuilder( entryPointFileFullPath: programPath, - targetFrameworkVersion: VirtualProjectBuildingCommand.TargetFrameworkVersion, + targetFramework: VirtualProjectBuildingCommand.TargetFramework, sourceText: SourceText.From(code, Encoding.UTF8)); var directives = FileLevelDirectiveHelpers.FindDirectives( @@ -5513,7 +5514,7 @@ public void Api() #!/program #:sdk Microsoft.NET.Sdk #:sdk Aspire.AppHost.Sdk@9.1.0 - #:property TargetFramework=net11.0 + #:property TargetFramework=net5.0 #:package System.CommandLine@2.0.0-beta4.22272.1 #:property LangVersion=preview Console.WriteLine(); @@ -5554,7 +5555,7 @@ public void Api() - net11.0 + net5.0 preview false $(Features);FileBasedProgram