Skip to content

Commit

Permalink
Update implicit global usings feature
Browse files Browse the repository at this point in the history
* Undo changes to VB projects
* For C#, projects use the `Using` itemgroup to generate global usings. Support aliasing and static imports with attributes.
* Use ImplicitUsings to determine if SDK-specific namespaces are imported by default.
  • Loading branch information
pranavkm committed Aug 12, 2021
1 parent 693a2c1 commit 08db8d7
Show file tree
Hide file tree
Showing 21 changed files with 350 additions and 310 deletions.
10 changes: 4 additions & 6 deletions src/BlazorWasmSdk/Sdk/Sdk.props
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,9 @@ Copyright (c) .NET Foundation. All rights reserved.

<Import Project="$(_BlazorWebAssemblyPropsFile)" />

<ItemGroup Condition=" '$(DisableImplicitNamespaceImports_BlazorWasm)' != 'true'
And '$(TargetFrameworkIdentifier)' == '.NETCoreApp'
And $([MSBuild]::VersionGreaterThanOrEquals('$(_TargetFrameworkVersionWithoutV)', '6.0'))">
<Import Include="Microsoft.Extensions.Configuration" />
<Import Include="Microsoft.Extensions.DependencyInjection" />
<Import Include="Microsoft.Extensions.Logging" />
<ItemGroup Condition="'$(ImplicitUsings)' == 'true' or '$(ImplicitUsings)' == 'enable'">
<Using Include="Microsoft.Extensions.Configuration" />
<Using Include="Microsoft.Extensions.DependencyInjection" />
<Using Include="Microsoft.Extensions.Logging" />
</ItemGroup>
</Project>
1 change: 0 additions & 1 deletion src/BlazorWasmSdk/Sdk/Sdk.targets
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ Copyright (c) .NET Foundation. All rights reserved.

<PropertyGroup>
<_BlazorWebAssemblyTargetsFile Condition="'$(_BlazorWebAssemblyTargetsFile)' == ''">$(MSBuildThisFileDirectory)..\targets\Microsoft.NET.Sdk.BlazorWebAssembly.Current.targets</_BlazorWebAssemblyTargetsFile>
<DisableImplicitNamespaceImports_BlazorWasm Condition="'$(DisableImplicitNamespaceImports_BlazorWasm)' == '' and '$(DisableImplicitNamespaceImports)' != 'true'">false</DisableImplicitNamespaceImports_BlazorWasm>
</PropertyGroup>

<ItemGroup>
Expand Down
117 changes: 117 additions & 0 deletions src/Tasks/Microsoft.NET.Build.Tasks/GenerateGlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Build.Framework;

namespace Microsoft.NET.Build.Tasks
{
public sealed class GenerateGlobalUsings : TaskBase
{
[Required]
public ITaskItem[] Usings { get; set; }

[Output]
public string[] Lines { get; set; }

protected override void ExecuteCore()
{
if (Usings.Length == 0)
{
Lines = Array.Empty<string>();
return;
}

var usings = Usings.Select(UsingInfo.Read)
.OrderBy(static k => k, UsingInfoComparer.Instance)
.Distinct(UsingInfoComparer.Instance);

var lines = new string[Usings.Length + 1];
lines[0] = "// <auto-generated/>";

var index = 1;
var lineBuilder = new StringBuilder();
foreach (var @using in usings)
{
lineBuilder.Clear();
lineBuilder.Append("global using ");

if (@using.Static)
{
lineBuilder.Append("static ");
}

if (!string.IsNullOrEmpty(@using.Alias))
{
lineBuilder.Append(@using.Alias)
.Append(" = ");
}

lineBuilder.Append("global::")
.Append(@using.Namespace)
.Append(';');

lines[index++] = lineBuilder.ToString();
}

Lines = lines;
}

private readonly struct UsingInfo
{
public static UsingInfo Read(ITaskItem taskItem)
{
return new UsingInfo(
taskItem.ItemSpec,
taskItem.GetBooleanMetadata("Static") == true,
taskItem.GetMetadata("Alias"));
}

private UsingInfo(string @namespace, bool @static, string alias)
{
Namespace = @namespace;
Static = @static;
Alias = alias;
}

public string Namespace { get; }
public bool Static { get; }
public string Alias { get; }
}

private sealed class UsingInfoComparer : IComparer<UsingInfo>, IEqualityComparer<UsingInfo>
{
public static readonly UsingInfoComparer Instance = new();

public int Compare(UsingInfo x, UsingInfo y)
{
var @static = x.Static.CompareTo(y.Static);
if (@static != 0)
{
return @static;
}

var alias = x.Alias.CompareTo(y.Alias);
if (alias != 0)
{
return alias;
}

return StringComparer.Ordinal.Compare(x.Namespace, y.Namespace);
}

public bool Equals(UsingInfo x, UsingInfo y)
{
return Compare(x, y) == 0;
}

public int GetHashCode(UsingInfo obj)
{
return StringComparer.Ordinal.GetHashCode(obj.Namespace);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<!--
***********************************************************************************************
Microsoft.NET.GenerateGlobalUsings.targets
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
created a backup copy. Incorrect changes to this file will make it
impossible to load or build your projects from the command-line or the IDE.
Copyright (c) .NET Foundation. All rights reserved.
***********************************************************************************************
-->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--
============================================================
GenerateGlobalUsings
Generates implicit namespace imports source to intermediate directory for C# projects
============================================================
-->
<UsingTask TaskName="GenerateGlobalUsings" AssemblyFile="$(MicrosoftNETBuildTasksAssembly)" />

<PropertyGroup>
<GeneratedGlobalUsingsFile Condition="'$(GeneratedGlobalUsingsFile)' ==''">$(IntermediateOutputPath)$(MSBuildProjectName).GlobalUsings.g$(DefaultLanguageSourceExtension)</GeneratedGlobalUsingsFile>
</PropertyGroup>

<!--
Note that this must run before every invocation of CoreCompile to ensure that all compiler
runs see the generated global usings. There is at least one scenario involving Xaml
where CoreCompile is invoked without other potential hooks such as Compile or CoreBuild,
etc., so we hook directly on to CoreCompile. Furthermore, we must run *after*
PrepareForBuild to ensure that the intermediate directory has been created.
Targets that generate Compile items are also expected to run before
BeforeCompile targets (common targets convention).
-->
<Target Name="GenerateGlobalUsings"
BeforeTargets="BeforeCompile;CoreCompile"
AfterTargets="PrepareForBuild"
Condition="@(Using->Count()) != 0">

<GenerateGlobalUsings Usings="@(Using)">
<Output TaskParameter="Lines" ItemName="_GlobalUsingLines" />
</GenerateGlobalUsings>

<WriteLinesToFile
File="$(GeneratedGlobalUsingsFile)"
Lines="@(_GlobalUsingLines)"
Overwrite="true"
WriteOnlyWhenDifferent="true" />

<ItemGroup>
<Compile Include="$(GeneratedGlobalUsingsFile)" />
<FileWrites Include="$(GeneratedGlobalUsingsFile)" />
</ItemGroup>
</Target>

</Project>

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,15 @@ Copyright (c) .NET Foundation. All rights reserved.
<DefineConstants>$(DefineConstants)TRACE</DefineConstants>
</PropertyGroup>

<!-- Implicit imports -->
<ItemGroup Condition="'$(ImplicitUsings)' == 'true' Or '$(ImplicitUsings)' == 'enable'">
<Using Include="System" />
<Using Include="System.Collections.Generic" />
<Using Include="System.IO" />
<Using Include="System.Linq" />
<Using Include="System.Net.Http" />
<Using Include="System.Threading" />
<Using Include="System.Threading.Tasks" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -82,49 +82,4 @@ Copyright (c) .NET Foundation. All rights reserved.

</ItemGroup>

<!-- Implicit imports -->
<ItemGroup Condition=" '$(DisableImplicitNamespaceImports_DotNet)' != 'true'
and '$(TargetFrameworkIdentifier)' == '.NETCoreApp'
and $([MSBuild]::VersionGreaterThanOrEquals($(_TargetFrameworkVersionWithoutV), '6.0'))">

<!-- Imports already defined as VB implicit imports are conditioned to not be added twice -->
<Import Include="System" Condition="'$(Language)' != 'VB'" />
<Import Include="System.Collections.Generic" Condition="'$(Language)' != 'VB'" />
<Import Include="System.IO" />
<Import Include="System.Linq" Condition="'$(Language)' != 'VB'" />
<Import Include="System.Net.Http" />
<Import Include="System.Threading" />
<Import Include="System.Threading.Tasks" Condition="'$(Language)' != 'VB'" />

</ItemGroup>

<!-- VB implicit imports -->
<ItemGroup Condition=" '$(DisableImplicitNamespaceImports)' != 'true'
and '$(Language)' == 'VB'
and '$(TargetFrameworkIdentifier)' == '.NETFramework'">
<!-- These namespaces are present in 2.0 Framework assemblies -->
<Import Include="Microsoft.VisualBasic" />
<Import Include="System" />
<Import Include="System.Collections" />
<Import Include="System.Collections.Generic" />
<Import Include="System.Data" />
<Import Include="System.Diagnostics" />
<!-- These namespaces are introduced in 3.5 Framework assemblies -->
<Import Include="System.Linq" Condition="('$(_TargetFrameworkVersionWithoutV)' != '') And ('$(_TargetFrameworkVersionWithoutV)' >= '3.5')"/>
<Import Include="System.Xml.Linq" Condition="('$(_TargetFrameworkVersionWithoutV)' != '') And ('$(_TargetFrameworkVersionWithoutV)' >= '3.5')"/>
<!-- This namespace is introduced in 4.0 Framework assemblies -->
<Import Include="System.Threading.Tasks" Condition="('$(_TargetFrameworkVersionWithoutV)' != '') And ('$(_TargetFrameworkVersionWithoutV)' >= '4.0')"/>
</ItemGroup>
<ItemGroup Condition=" '$(DisableImplicitNamespaceImports)' != 'true'
and '$(Language)' == 'VB'
and '$(_IsNETCoreOrNETStandard)' == 'true'">
<Import Include="Microsoft.VisualBasic" />
<Import Include="System" />
<Import Include="System.Collections" />
<Import Include="System.Collections.Generic" />
<Import Include="System.Diagnostics" />
<Import Include="System.Linq" />
<Import Include="System.Xml.Linq" />
<Import Include="System.Threading.Tasks" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,30 @@ Copyright (c) .NET Foundation. All rights reserved.
***********************************************************************************************
-->
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Condition=" '$(DisableImplicitNamespaceImports)' != 'true' and '$(TargetFrameworkIdentifier)' == '.NETFramework'">
<!-- These namespaces are present in 2.0 Framework assemblies -->
<Import Include="Microsoft.VisualBasic" />
<Import Include="System" />
<Import Include="System.Collections" />
<Import Include="System.Collections.Generic" />
<Import Include="System.Data" />
<Import Include="System.Diagnostics" />
<!-- These namespaces are introduced in 3.5 Framework assemblies -->
<Import Include="System.Linq" Condition=" '$(_TargetFrameworkVersionWithoutV)' >= '3.5' "/>
<Import Include="System.Xml.Linq" Condition=" '$(_TargetFrameworkVersionWithoutV)' >= '3.5' "/>
<!-- This namespace is introduced in 4.0 Framework assemblies -->
<Import Include="System.Threading.Tasks" Condition=" '$(_TargetFrameworkVersionWithoutV)' >= '4.0' "/>
</ItemGroup>
<ItemGroup Condition=" '$(DisableImplicitNamespaceImports)' != 'true' and '$(_IsNETCoreOrNETStandard)' == 'true'">
<Import Include="Microsoft.VisualBasic" />
<Import Include="System" />
<Import Include="System.Collections" />
<Import Include="System.Collections.Generic" />
<Import Include="System.Diagnostics" />
<Import Include="System.Linq" />
<Import Include="System.Xml.Linq" />
<Import Include="System.Threading.Tasks" />
</ItemGroup>
<PropertyGroup Condition="'$(DisableImplicitConfigurationDefines)' != 'true' and '$(Configuration)' != ''">
<ImplicitConfigurationDefine>$(Configuration.ToUpperInvariant())</ImplicitConfigurationDefine>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ Copyright (c) .NET Foundation. All rights reserved.
<ComputeNETCoreBuildOutputFiles Condition=" '$(ComputeNETCoreBuildOutputFiles)' == '' and '$(TargetFrameworkIdentifier)' == '.NETCoreApp'">true</ComputeNETCoreBuildOutputFiles>
<_GenerateRuntimeConfigurationPropertyInputsCache Condition="'$(_GenerateRuntimeConfigurationPropertyInputsCache)' == ''">$(IntermediateOutputPath)$(MSBuildProjectName).genruntimeconfig.cache</_GenerateRuntimeConfigurationPropertyInputsCache>
<_GenerateRuntimeConfigurationPropertyInputsCache>$([MSBuild]::NormalizePath($(MSBuildProjectDirectory), $(_GenerateRuntimeConfigurationPropertyInputsCache)))</_GenerateRuntimeConfigurationPropertyInputsCache>
<DisableImplicitNamespaceImports Condition="'$(DisableImplicitNamespaceImports)'==''">$(DisableImplicitFrameworkReferences)</DisableImplicitNamespaceImports>
</PropertyGroup>

<ItemGroup>
Expand Down Expand Up @@ -1129,7 +1128,7 @@ Copyright (c) .NET Foundation. All rights reserved.
<Import Project="$(MSBuildThisFileDirectory)Microsoft.NET.DisableStandardFrameworkResolution.targets" Condition="'$(DisableStandardFrameworkResolution)' == 'true'" />
<Import Project="$(MSBuildThisFileDirectory)Microsoft.NET.DesignerSupport.targets" />
<Import Project="$(MSBuildThisFileDirectory)Microsoft.NET.GenerateAssemblyInfo.targets" Condition="'$(UsingNETSdkDefaults)' == 'true'"/>
<Import Project="$(MSBuildThisFileDirectory)Microsoft.NET.GenerateImplicitNamespaceImports.targets" Condition="'$(DisableImplicitNamespaceImports)' != 'true' and '$(Language)' == 'C#'"/>
<Import Project="$(MSBuildThisFileDirectory)Microsoft.NET.GenerateGlobalUsings.targets" Condition="'$(Language)' == 'C#'"/>
<Import Project="$(MSBuildThisFileDirectory)Microsoft.NET.GenerateSupportedRuntime.targets" />
<Import Project="$(MSBuildThisFileDirectory)Microsoft.NET.ComposeStore.targets" Condition="'$(UsingNETSdkDefaults)' == 'true'" />
<Import Project="$(MSBuildThisFileDirectory)Microsoft.NET.CrossGen.targets" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
using Microsoft.NET.TestFramework.Assertions;
using Microsoft.NET.TestFramework.Commands;
using Microsoft.NET.TestFramework.ProjectConstruction;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
Expand Down Expand Up @@ -276,7 +278,7 @@ static int Last2DigitsTo0(int versionBuild)
RuntimePackNamePatterns='Microsoft.NETCore.App.Test.RuntimePack'
RuntimePackRuntimeIdentifiers='any'
/>
<FrameworkReference Include='Microsoft.NETCore.App.Test'/>
</ItemGroup>");
project.Root.Add(itemGroup);
Expand Down
Loading

0 comments on commit 08db8d7

Please sign in to comment.