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

Allow modifying set of implicit global usings for .NET 6 projects #7488

Closed
Tracked by #8292
drewnoakes opened this issue Aug 16, 2021 · 13 comments · Fixed by #8438
Closed
Tracked by #8292

Allow modifying set of implicit global usings for .NET 6 projects #7488

drewnoakes opened this issue Aug 16, 2021 · 13 comments · Fixed by #8438
Assignees
Labels
Feature-Project-Properties-Designer The new project property pages which replace the legacy AppDesigner Resolution-Fixed The bug has been fixed, refer to the milestone to see in which release it was fixed. Triage-Approved Reviewed and prioritized
Milestone

Comments

@drewnoakes
Copy link
Member

.NET 6 provides a new feature, "implicit global usings".

We should add tooling support to it in the new Project Property UI.

Relates to dotnet/sdk#19521

At a high level this involves:

  • A new <ImplicitUsings> property, with values of enable, true and disable
  • New <Using Include="..." ... /> items

The property will be straightforward, but the new items will likely require some custom UI as they are not just a simple string list and allow metadata such as Alias and Static.

The MSBuild XSD was updated with these values in dotnet/msbuild#6755

@drewnoakes drewnoakes added the Feature-Project-Properties-Designer The new project property pages which replace the legacy AppDesigner label Aug 16, 2021
@drewnoakes
Copy link
Member Author

true and enable are aliases. We should only define one in the UI (a checkbox would suffice for now) and we should alias these two values via an interceptor.

@drewnoakes
Copy link
Member Author

As custom UI is potentially challenging here, an intermediate solution may be to support multi-line text, with values of the form:

System
System.Collections.Generic
Foo = MyNamespace.Bar
static Foo.Bar

Which would map to:

<ItemGroup>
  <Using Include="System" />
  <Using Include="System.Collections.Generic" />
  <Using Include="MyNamespace.Bar" Alias="Foo" />
  <Using Include="Foo.Bar" Static="true" />
</ItemGroup>

@drewnoakes
Copy link
Member Author

@drewnoakes
Copy link
Member Author

drewnoakes commented Aug 22, 2021

Also investigate DisableImplicitNamespaceImports.

It seems that this varies by project language, which we will have to respect in the UI:

  • DisableImplicitNamespaceImports is VB only
  • ImplicitUsings is C# only

See the first few bullet points on dotnet/sdk#19521 for info.

@marcpopMSFT
Copy link
Member

Thanks for tracking that down. I thought for a second we'd just left the extra property in by mistake but it looks like it existed before for VB and they didn't want to make the breaking change.

@jjmew jjmew added this to the 17.0 milestone Aug 24, 2021
@jjmew jjmew added the Triage-Approved Reviewed and prioritized label Aug 24, 2021
@drewnoakes drewnoakes modified the milestones: 17.0, 17.1 Aug 30, 2021
@drewnoakes drewnoakes changed the title Support .NET 6 implicit global using feature in the new property pages Allow modifying set of implicit global usings for .NET 6 projects Aug 30, 2021
@drewnoakes
Copy link
Member Author

#7512 adds a check box that controls whether the feature is enabled.

The ability to modify the set of includes is still pending, and this issue is now tracking that.

@sam-wheat
Copy link

I came across this thread because after using VS2022 for a week I wanted to find out why the global/implicit usings implementation is designed the way it is. I am disappointed with the current design because I feel like it excludes configurability and usability in favor of no other perceptible gain except, perhaps, brevity.

Specifically:

1.) There is no facility for the developer to maintain their own set of implicit usings. This needs to be a Visual Studio setting so the usings are created for each new project.

2.) Developer needs to be able to choose if they want to use a single file dedicated to global usings. If so, developer needs to be able to supply their own name for the file.

3.) VS needs to create the named global usings file when project is created, if applicable.

Items 2 and 3 above will give VS the ability to create a using statement in the correct file if the developer uses intellisense to create the using statement. The current design breaks the intellisense feature (using statement is added to current file only - not global usings file).

Items 2 and 3 eliminate the need to create a global usings file in the obj folder (not that there was a need to begin with).

Proposed functionality will create a new global usings file when a project is created and populate that file with SDK + developer defined usings statements (implicit). Global usings file will be readable and editable by the developer and will allow VS intellisense to continue to work correctly.

@drewnoakes
Copy link
Member Author

@sam-wheat we definitely want to provide control over the set of implicit usings added to the project.

Despite the lack of UI for this currently, it's still possible to specify your own set of usings and share them across projects.

For example, in a Directory.Build.props file, you can add:

<ItemGroup>
  <Using Remove="System.Collections.Generic" />
  <Using Include="My.Collections.Namespace" />
</ItemGroup>

...and this will be picked up by all projects beneath the folder that contains that file.

You can also create a .cs file with eg: global using My.Collections.Namespace;, and link that source file into your projects.

@sam-wheat
Copy link

Thank you Drew. Couple questions about Directory.Build.props:
Will VS create this file when a .sln is created and populate it with selected usings?
Will VS use this file when populating a using from Intellisense?
Given the availability of Directory.Build.props what is the purpose of the usings file created in the obj folder?

BTW I like the idea of a standardized name/location for global usings.

@drewnoakes
Copy link
Member Author

Will VS create this file when a .sln is created and populate it with selected usings?

VS doesn't create this file. You'll need to do it manually.

Given the availability of Directory.Build.props what is the purpose of the usings file created in the obj folder?

The process is:

  • project declares usings in MSBuild files (.csproj, .props, etc)
  • during build the .cs file is generated in the obj folder
  • compiler uses the .cs file

Will VS use this file when populating a using from Intellisense?

Yes.

BTW I like the idea of a standardized name/location for global usings.

Directory.Build.props is the best place for standardising things across a solution, or perhaps across the src or test folder, for example. There's no UI support for this in VS currently, but it's not hard to set up manually. You can add the file as a solution item in Solution Explorer.

@leaderanalytics
Copy link

I thought I would give it a try for kicks and giggles. Added Directory.Build.props in the same folder as my .sln:

<Project>
	<ItemGroup>
		<Using Include="Autofac"/>
		<Using Include="Autofac.Extensions.DependencyInjection"/>
		// etc...

On build I get multiple errors becuse not all of my projects are referencing assemblies mentioned in Directory.Build.props. The error occurs in the generated file:

// <auto-generated/>
global using global::Autofac;				// valid
global using global::Autofac.Extensions.DependencyInjection;			// error

I tried referencing a .cs file I created also in the same folder and as the .sln. Added the file to one of my projects as a link and opend it. Not surprisingly I get the same errors as the generated file:

global using Autofac;		// valid
global using Autofac.Extensions.DependencyInjection;		// error

https://docs.microsoft.com/en-us/visualstudio/msbuild/customize-your-build?view=vs-2022

dotnet/sdk#19521

@drewnoakes
Copy link
Member Author

@leaderanalytics the following might be useful for you. I'm not saying this is supported or recommended, but in my limited testing it seems to work. If you add the Using item in a Directory.Build.targets file, you can condition them based upon the presence of a particular PackageReference in each project that picks the file:

<Project InitialTargets="AddGlobalUsingItems">
  <Target Name="AddGlobalUsingItems">
    <ItemGroup>
      <Using Include="Autofac" Condition="'%(PackageReference.Identity)' == 'Autofac'" />
    </ItemGroup>
  </Target>
</Project>

Unfortunately this requires an MSBuild <Target>, as the form of the Condition expression is not supported in evaluation, only during build (and therefore only in targets).

@drewnoakes drewnoakes modified the milestones: 17.2, 17.3 Mar 14, 2022
@drewnoakes drewnoakes modified the milestones: 17.3, 17.4 Jun 5, 2022
@adamint
Copy link
Member

adamint commented Jun 29, 2022

We may be able to take advantage of the MultiStringSelector editor for this.

@drewnoakes drewnoakes removed their assignment Jul 18, 2022
@ghost ghost added the Resolution-Fixed The bug has been fixed, refer to the milestone to see in which release it was fixed. label Sep 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature-Project-Properties-Designer The new project property pages which replace the legacy AppDesigner Resolution-Fixed The bug has been fixed, refer to the milestone to see in which release it was fixed. Triage-Approved Reviewed and prioritized
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants