Skip to content

Support traversal projects #207

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

Merged
merged 2 commits into from
Apr 21, 2024
Merged

Support traversal projects #207

merged 2 commits into from
Apr 21, 2024

Conversation

baronfel
Copy link
Collaborator

@baronfel baronfel commented Apr 21, 2024

Traversal projects are a nice alternative to solutions, but they don't have great IDE support because they lack many of the targets/properties that 'normal' projects have. This PR introduces support for traversal projects basically by detecting them just enough to get their ProjectReferences, and then doing nothing else with them.

Base automatically changed from support-projects-with-missing-imports to main April 21, 2024 19:10
@baronfel baronfel force-pushed the support-traversal-projects branch from 3a7a3fa to f5a4453 Compare April 21, 2024 19:29
Comment on lines +647 to +650
match pi.GetProperty "IsTraversal" with
| null -> doDesignTimeBuild ()
| p when Boolean.Parse(p.EvaluatedValue) = false -> doDesignTimeBuild ()
| _ -> yieldTraversalProject ()
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The core change for the 'classic' workspace loader is here - depending on what kind of project this is we pivot behavior to just finding projectreferences, or doing a full design-time-build.

Comment on lines +671 to +718
let getP2PRefs (project) =
match project with
| TraversalProject p ->
let references =
p.Items
|> Seq.filter (fun p -> p.ItemType = "ProjectReference")
|> Seq.toList

let mappedItems = ResizeArray()

for item in references do
let relativePath = item.EvaluatedInclude
let fullPath = Path.GetFullPath(relativePath, item.Project.Directory)

{
RelativePath = relativePath
ProjectFileName = fullPath
TargetFramework = ""
}
|> mappedItems.Add

let tfms =
if p.HasMetadata "TargetFramework" then
p.GetMetadataValue "TargetFramework"
Seq.toList mappedItems

| StandardProject p ->
p.Items
|> Seq.choose (fun p ->
if
p.ItemType
<> "_MSBuildProjectReferenceExistent"
then
None
else
p.GetMetadataValue "TargetFrameworks"
let relativePath = p.EvaluatedInclude
let path = p.GetMetadataValue "FullPath"

{
RelativePath = relativePath
ProjectFileName = path
TargetFramework = tfms
}
)
let tfms =
if p.HasMetadata "TargetFramework" then
p.GetMetadataValue "TargetFramework"
else
p.GetMetadataValue "TargetFrameworks"

let getCompileItems (LoadedProject project) =
project.Items
Some {
RelativePath = relativePath
ProjectFileName = path
TargetFramework = tfms
}
)
|> Seq.toList
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The only logical operation that we need for Traversal Projects is finding ProjectReferences, which is pretty much just a lookup for ProjectReference items. Unlike in a 'normal' project, these are able to be used because we don't really have to handle the intricacies of the ProjectReference protocol

Comment on lines +1110 to +1122
|> Seq.choose (fun pn ->
match pn.ProjectInstance.GetProperty("IsTraversal") with
| null ->
ProjectGraphEntryPoint pn.ProjectInstance.FullPath
|> Some
| p ->
match bool.TryParse(p.EvaluatedValue) with
| true, true -> None
| true, false ->
ProjectGraphEntryPoint pn.ProjectInstance.FullPath
|> Some
| false, _ -> None
)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Here's the main impact for the graph build loader - if any of the project nodes are traversal projects, editors won't really know what to do with them so just...don't report them.

Comment on lines +1442 to +1445
let referencedProjects =
match project with
| ProjectLoader.LoadedProjectInfo.StandardProjectInfo p -> p.ReferencedProjects
| ProjectLoader.LoadedProjectInfo.TraversalProjectInfo p -> p
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

similarly for the standard loader, once we load the outer project if it was a traversal project we can just walk its ProjectReferences instead of creating an entirely new ProjectOptions structure to hold the .ReferencedProjects member.

@baronfel baronfel merged commit fec9602 into main Apr 21, 2024
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants