Skip to content
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 spec for dotnet run file.cs #47020

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open

Conversation

jjonescz
Copy link
Member

@jjonescz jjonescz commented Feb 21, 2025

@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged Request triage from a team member label Feb 21, 2025
@jjonescz jjonescz marked this pull request as ready for review February 21, 2025 15:57
@Copilot Copilot bot review requested due to automatic review settings February 21, 2025 15:57
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@nkolev92 nkolev92 requested a review from a team February 27, 2025 18:38
@Nigusu-Allehu Nigusu-Allehu self-requested a review February 27, 2025 18:40
@baronfel baronfel added Area-run-file Items related to the "dotnet run <file>" effort and removed untriaged Request triage from a team member Area-CLI labels Feb 27, 2025
@RikkiGibson
Copy link
Contributor

RikkiGibson commented Feb 27, 2025

So, suppose /myapps/ is open in the IDE. When we are viewing /myapps/utils.cs, we will have to go through every /myapps/app1.cs, /myapps/app2.cs and so on, and add it as a target in the drop-down list on the top left, right? And the contents of each app.cs are visible to utils.cs in the context of that app-specific build, but, it won't be practical to refer to types etc. declared in one of the app files from within utils.cs, because they'd kinda have to be copy-pasted within each app file anyway.

All of that seems fine to me. Just putting together the larger picture in my mind.

Also, will it be possible to make app.cs an entry in a solution file just like a project would be?

@jjonescz
Copy link
Member Author

jjonescz commented Feb 28, 2025

add it as a target in the drop-down list on the top left, right?

You mean like launch target? I guess yes, same as if app1 and app2 were regular projects.

And the contents of each app.cs are visible to utils.cs in the context of that app-specific build

No, the app1 and app2 projects will reference utils but that's it, i.e., apps can see utils but not the other way around. Imagine the project structure after "grow up" (see "Multiple entrypoints" section) - the behavior before "grow up" is equivalent. I will clarify.

Also, will it be possible to make app.cs an entry in a solution file just like a project would be?

I think you can add arbitrary files as "Solution Files" even today. You would have to add all your project-less .cs files though, adding just the entry file and having IDE discover the rest is a possible future feature I suppose.

@RikkiGibson
Copy link
Contributor

You mean like launch target? I guess yes, same as if app1 and app2 were regular projects.

I was thinking of this one:

image

I guess it is called the "projects" list, though, it is really populated with each TFM for each project.

It sounds like actually utils.cs is supposed to have its own non-executable virtual project. So that list would only have the one item in it.

@chsienki
Copy link
Member

chsienki commented Mar 3, 2025

Getting off topic a bit, but just to follow up with Rikki's comments, if a source file is part of multiple projects via TFM as shown, or by source linking, it shows each project it's a part of:

image

So conceptually it would make sense to have each entry file as a 'project' that the shared files would be a part of.

@RikkiGibson
Copy link
Contributor

So conceptually it would make sense to have each entry file as a 'project' that the shared files would be a part of.

This is a key decision point in the design though. Either we see the "shared files" project as a separate project which is <ProjectReferenced>'d into the entry point projects, or we see it as "source included", with different "copies" of the shared files in each entry point. This affects whether internal declarations of the "shared files" accessible to the "entry point" projects or not, for example. (I doubt we would want to use IVTs in the virtual projects.)

When we get further along with this, it would probably be good to write up several more examples of file structures here. That is, executable and non-executable files at various levels of nesting, with and without project files already present on disk, and what we think should happen in terms of which virtual projects exist and what the virtual projects contents are (like which files are included in them).

@chsienki
Copy link
Member

chsienki commented Mar 3, 2025

Either we see the "shared files" project as a separate project which is <ProjectReferenced>'d into the entry point projects, or we see it as "source included", with different "copies" of the shared files in each entry point.

Personally, I would 100% expect it to be a "source included" model.

@jjonescz
Copy link
Member Author

jjonescz commented Mar 4, 2025

Currently the proposal describes the "project references" model, not "source included". That's because, in my opinion, we strive for the simplest "implicit project file" experience. "Source included", "IVTs", etc, are advanced scenarios and if we did them and wanted to preserve the semantics during "grow up", we would need to generate complicated project files, but we want to avoid that.

I don't see any problems with "project references" model. Yes, your shared utility classes need to be public, not internal, but that doesn't sound like a bad thing.

@chsienki
Copy link
Member

chsienki commented Mar 4, 2025

Currently the proposal describes the "project references" model, not "source included". That's because, in my opinion, we strive for the simplest "implicit project file" experience. "Source included", "IVTs", etc, are advanced scenarios and if we did them and wanted to preserve the semantics during "grow up", we would need to generate complicated project files, but we want to avoid that.

I don't see any problems with "project references" model. Yes, your shared utility classes need to be public, not internal, but that doesn't sound like a bad thing.

Hmm, from the spec I can see why that would be the case, but it does seem extremely confusing as its kind of counter to the way it works (at least in my head) with the no project file case. Because if I have a case like

  • App1.cs
  • Utils.cs

Then it seems intuitive (to me) that there is one virtual project file App1.csproj that includes both files. App1.cs should be able to see internals of Utils.cs.

If I then add another entry point:

  • App1.cs
  • App2.cs
  • Utils.cs

Then (my) intuition follows that there are two virtual project files:

  • App1.csproj
    • App1.cs
    • Utils.cs
  • App2.csproj
    • App2.cs
    • Utils.cs

So effectively a source-shared model where both projects can see internals. Not that Utils.cs is in a shared project needing public visibility. With the project-ref model either the single entry-point case is odd because it can't see internals, or they are different and then adding another entry point changes the semantics which seems even worse?

I think a shared source model makes it easier to keep the semantics similar to dotnet new where you just get a vanilla project file if there's only one entry point. For multi entry-point grow up you get close to a vanilla file just with explicit excludes of the other entry points. Effectively 'overlapping' projects on disk.

I'm not actually sure how much sense it makes to grow up project files on an individual basis, but it also seems weird you end up with different things depending on having 1 or N entry points. Because the 'project-ref' model is sort of treating the folder as an implicit .sln, vs multiple overlaid projects.

I appreciate this all seems kind of nit-picky, but I think it's really important we think through exactly how grow up works if we allow implicit file inclusion as I think it really muddies these stories.

@jjonescz
Copy link
Member Author

jjonescz commented Mar 4, 2025

seems weird you end up with different things depending on having 1 or N entry points

You're right, it indeed seems confusing if going from 1 to multiple entrypoints changes behavior like that, I haven't fully realized that's going to happen.

Given that, I agree that source shared model seems better. Thanks.

Or perhaps IVT wouldn't be that bad either.

Copy link
Member

@DamianEdwards DamianEdwards left a comment

Choose a reason for hiding this comment

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

Good starting point. A few comments but nothing that should be considered blocking.

Copy link
Contributor

@nkolev92 nkolev92 left a comment

Choose a reason for hiding this comment

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

Really excited about this feature!

I think we should reconsider the globbing behavior.
The current approach optimizes for the fact that these files will become projects eventually, but the motivation calls out scripting as a scenario.
I feel like for scripting, you'd prefer to just load the single file and just go from there.
Think having the cs file in the root of the repo for example.
Another idea would be do build authoring in the cs file eventually. Importing nested folders would conflict with that.

@jjonescz
Copy link
Member Author

jjonescz commented Mar 5, 2025

The current approach optimizes for the fact that these files will become projects eventually, but the motivation calls out scripting as a scenario.

Consider that scripts often grow up into more complicated standalone utility programs.

Think having the cs file in the root of the repo for example.
Another idea would be do build authoring in the cs file eventually. Importing nested folders would conflict with that.

I guess it wouldn't be as straightforward, but I wouldn't say it conflicts. You can absolutely have build/script.cs and then do dotnet run build.

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 documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants