-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add #:project
directive
#49311
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add #:project
directive
#49311
Changes from all commits
c4bb180
9ee01d4
c37558b
7b1252a
01698b7
6529704
fc75bf8
e5e1447
ee2f220
d2b66c2
9eea996
304b90f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -58,6 +58,56 @@ internal sealed class VirtualProjectBuildingCommand : CommandBase | |
"MSBuild.rsp", | ||
]; | ||
|
||
internal static readonly string TargetOverrides = """ | ||
<!-- | ||
Override targets which don't work with project files that are not present on disk. | ||
See https://github.com/NuGet/Home/issues/14148. | ||
--> | ||
<Target Name="_FilterRestoreGraphProjectInputItems" | ||
DependsOnTargets="_LoadRestoreGraphEntryPoints"> | ||
<!-- No-op, the original output is not needed by the overwritten targets. --> | ||
</Target> | ||
<Target Name="_GetAllRestoreProjectPathItems" | ||
DependsOnTargets="_FilterRestoreGraphProjectInputItems;_GenerateRestoreProjectPathWalk" | ||
Returns="@(_RestoreProjectPathItems)"> | ||
<!-- Output from dependency _GenerateRestoreProjectPathWalk. --> | ||
</Target> | ||
<Target Name="_GenerateRestoreGraph" | ||
DependsOnTargets="_FilterRestoreGraphProjectInputItems;_GetAllRestoreProjectPathItems;_GenerateRestoreGraphProjectEntry;_GenerateProjectRestoreGraph" | ||
Returns="@(_RestoreGraphEntry)"> | ||
<!-- Output partly from dependency _GenerateRestoreGraphProjectEntry and _GenerateProjectRestoreGraph. --> | ||
<ItemGroup> | ||
<_GenerateRestoreGraphProjectEntryInput Include="@(_RestoreProjectPathItems)" Exclude="$(MSBuildProjectFullPath)" /> | ||
</ItemGroup> | ||
<MSBuild | ||
BuildInParallel="$(RestoreBuildInParallel)" | ||
Projects="@(_GenerateRestoreGraphProjectEntryInput)" | ||
Targets="_GenerateRestoreGraphProjectEntry" | ||
Properties="$(_GenerateRestoreGraphProjectEntryInputProperties)"> | ||
<Output | ||
TaskParameter="TargetOutputs" | ||
ItemName="_RestoreGraphEntry" /> | ||
</MSBuild> | ||
<MSBuild | ||
BuildInParallel="$(RestoreBuildInParallel)" | ||
Projects="@(_GenerateRestoreGraphProjectEntryInput)" | ||
Targets="_GenerateProjectRestoreGraph" | ||
Properties="$(_GenerateRestoreGraphProjectEntryInputProperties)"> | ||
<Output | ||
TaskParameter="TargetOutputs" | ||
ItemName="_RestoreGraphEntry" /> | ||
</MSBuild> | ||
</Target> | ||
"""; | ||
|
||
private ImmutableArray<CSharpDirective> _directives; | ||
|
||
public VirtualProjectBuildingCommand( | ||
|
@@ -468,6 +518,7 @@ public static void WriteProjectFile( | |
var sdkDirectives = directives.OfType<CSharpDirective.Sdk>(); | ||
var propertyDirectives = directives.OfType<CSharpDirective.Property>(); | ||
var packageDirectives = directives.OfType<CSharpDirective.Package>(); | ||
var projectDirectives = directives.OfType<CSharpDirective.Project>(); | ||
|
||
string sdkValue = "Microsoft.NET.Sdk"; | ||
|
||
|
@@ -607,6 +658,25 @@ public static void WriteProjectFile( | |
writer.WriteLine(" </ItemGroup>"); | ||
} | ||
|
||
if (projectDirectives.Any()) | ||
{ | ||
writer.WriteLine(""" | ||
<ItemGroup> | ||
"""); | ||
|
||
foreach (var projectReference in projectDirectives) | ||
{ | ||
writer.WriteLine($""" | ||
<ProjectReference Include="{EscapeValue(projectReference.Name)}" /> | ||
"""); | ||
|
||
processedDirectives++; | ||
} | ||
|
||
writer.WriteLine(" </ItemGroup>"); | ||
} | ||
|
||
Debug.Assert(processedDirectives + directives.OfType<CSharpDirective.Shebang>().Count() == directives.Length); | ||
|
||
if (isVirtualProject) | ||
|
@@ -643,35 +713,8 @@ public static void WriteProjectFile( | |
"""); | ||
} | ||
|
||
writer.WriteLine(""" | ||
<!-- | ||
Override targets which don't work with project files that are not present on disk. | ||
See https://github.com/NuGet/Home/issues/14148. | ||
--> | ||
<Target Name="_FilterRestoreGraphProjectInputItems" | ||
DependsOnTargets="_LoadRestoreGraphEntryPoints" | ||
Returns="@(FilteredRestoreGraphProjectInputItems)"> | ||
<ItemGroup> | ||
<FilteredRestoreGraphProjectInputItems Include="@(RestoreGraphProjectInputItems)" /> | ||
</ItemGroup> | ||
</Target> | ||
<Target Name="_GetAllRestoreProjectPathItems" | ||
DependsOnTargets="_FilterRestoreGraphProjectInputItems" | ||
Returns="@(_RestoreProjectPathItems)"> | ||
<ItemGroup> | ||
<_RestoreProjectPathItems Include="@(FilteredRestoreGraphProjectInputItems)" /> | ||
</ItemGroup> | ||
</Target> | ||
<Target Name="_GenerateRestoreGraph" | ||
DependsOnTargets="_FilterRestoreGraphProjectInputItems;_GetAllRestoreProjectPathItems;_GenerateRestoreGraphProjectEntry;_GenerateProjectRestoreGraph" | ||
Returns="@(_RestoreGraphEntry)"> | ||
<!-- Output from dependency _GenerateRestoreGraphProjectEntry and _GenerateProjectRestoreGraph --> | ||
</Target> | ||
"""); | ||
writer.WriteLine(); | ||
writer.WriteLine(TargetOverrides); | ||
} | ||
|
||
writer.WriteLine(""" | ||
|
@@ -943,16 +986,22 @@ private CSharpDirective() { } | |
"sdk" => Sdk.Parse(errors, sourceFile, span, directiveKind, directiveText), | ||
"property" => Property.Parse(errors, sourceFile, span, directiveKind, directiveText), | ||
"package" => Package.Parse(errors, sourceFile, span, directiveKind, directiveText), | ||
"project" => Project.Parse(errors, sourceFile, span, directiveText), | ||
_ => ReportError<Named>(errors, sourceFile, span, string.Format(CliCommandStrings.UnrecognizedDirective, directiveKind, sourceFile.GetLocationString(span))), | ||
}; | ||
} | ||
|
||
private static T? ReportError<T>(ImmutableArray<SimpleDiagnostic>.Builder? errors, SourceFile sourceFile, TextSpan span, string message, Exception? inner = null) | ||
{ | ||
ReportError(errors, sourceFile, span, message, inner); | ||
return default; | ||
} | ||
|
||
private static void ReportError(ImmutableArray<SimpleDiagnostic>.Builder? errors, SourceFile sourceFile, TextSpan span, string message, Exception? inner = null) | ||
{ | ||
if (errors != null) | ||
{ | ||
errors.Add(new SimpleDiagnostic { Location = sourceFile.GetFileLinePositionSpan(span), Message = message }); | ||
return default; | ||
} | ||
else | ||
{ | ||
|
@@ -1088,6 +1137,44 @@ private Package() { } | |
}; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// <c>#:project</c> directive. | ||
/// </summary> | ||
public sealed class Project : Named | ||
{ | ||
private Project() { } | ||
|
||
public static Project Parse(ImmutableArray<SimpleDiagnostic>.Builder? errors, SourceFile sourceFile, TextSpan span, string directiveText) | ||
{ | ||
try | ||
{ | ||
// If the path is a directory like '../lib', transform it to a project file path like '../lib/lib.csproj'. | ||
// Also normalize blackslashes to forward slashes to ensure the directive works on all platforms. | ||
var sourceDirectory = Path.GetDirectoryName(sourceFile.Path) ?? "."; | ||
var resolvedProjectPath = Path.Combine(sourceDirectory, directiveText.Replace('\\', '/')); | ||
if (Directory.Exists(resolvedProjectPath)) | ||
{ | ||
var fullFilePath = MsbuildProject.GetProjectFileFromDirectory(resolvedProjectPath).FullName; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A few lines above we normalize There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider user writing Normalization here isn't necessary for that to work, but I guess we could normalize for other reasons. But the current behavior (without normalization) should be consistent with what There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not obvious to me that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep MSBuild "solves" this for us as paths there are normalized. We can decide to simply pass through what the user types in the directive directly I think. |
||
directiveText = Path.GetRelativePath(relativeTo: sourceDirectory, fullFilePath); | ||
} | ||
else if (!File.Exists(resolvedProjectPath)) | ||
{ | ||
throw new GracefulException(CliStrings.CouldNotFindProjectOrDirectory, resolvedProjectPath); | ||
} | ||
} | ||
catch (GracefulException e) | ||
{ | ||
ReportError(errors, sourceFile, span, string.Format(CliCommandStrings.InvalidProjectDirective, sourceFile.GetLocationString(span), e.Message), e); | ||
} | ||
|
||
return new Project | ||
{ | ||
Span = span, | ||
Name = directiveText, | ||
}; | ||
} | ||
} | ||
} | ||
|
||
/// <summary> | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.