Skip to content

Commit 39b58fe

Browse files
committed
Don't import System when it's already imported by global using
1 parent ea8aa10 commit 39b58fe

File tree

4 files changed

+27
-51
lines changed

4 files changed

+27
-51
lines changed

src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Runtime/CSharpUseSpanBasedStringConcat.Fixer.cs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,6 @@ private protected override SyntaxNode ReplaceInvocationMethodName(SyntaxGenerato
2121
return invocationSyntax.ReplaceNode(oldNameSyntax, newNameSyntax);
2222
}
2323

24-
private protected override bool IsSystemNamespaceImported(Project project, IReadOnlyList<SyntaxNode> namespaceImports)
25-
{
26-
foreach (var import in namespaceImports)
27-
{
28-
if (import is UsingDirectiveSyntax { Name: IdentifierNameSyntax { Identifier.ValueText: nameof(System) } })
29-
return true;
30-
}
31-
32-
return false;
33-
}
34-
3524
private protected override IOperation WalkDownBuiltInImplicitConversionOnConcatOperand(IOperation operand)
3625
{
3726
return UseSpanBasedStringConcat.CSharpWalkDownBuiltInImplicitConversionOnConcatOperand(operand);

src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/UseSpanBasedStringConcat.Fixer.cs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.
22

33
using System;
4-
using System.Collections.Generic;
54
using System.Collections.Immutable;
65
using System.Diagnostics.CodeAnalysis;
76
using System.Linq;
@@ -23,11 +22,10 @@ public abstract class UseSpanBasedStringConcatFixer : CodeFixProvider
2322
private protected const string AsSpanName = nameof(MemoryExtensions.AsSpan);
2423
private protected const string AsSpanStartParameterName = "start";
2524
private protected const string ToStringName = nameof(ToString);
25+
private static readonly SyntaxAnnotation s_asSpanSymbolAnnotation = new("SymbolId", "System.MemoryExtensions");
2626

2727
private protected abstract SyntaxNode ReplaceInvocationMethodName(SyntaxGenerator generator, SyntaxNode invocationSyntax, string newName);
2828

29-
private protected abstract bool IsSystemNamespaceImported(Project project, IReadOnlyList<SyntaxNode> namespaceImports);
30-
3129
private protected abstract IOperation WalkDownBuiltInImplicitConversionOnConcatOperand(IOperation operand);
3230

3331
private protected abstract bool IsNamedArgument(IArgumentOperation argumentOperation);
@@ -110,13 +108,6 @@ async Task<Document> FixConcatOperationChain(CancellationToken cancellationToken
110108

111109
SyntaxNode newRoot = generator.ReplaceNode(root, concatExpressionSyntax, concatMethodInvocationSyntax);
112110

113-
// Import 'System' namespace if it's absent.
114-
if (!IsSystemNamespaceImported(context.Document.Project, generator.GetNamespaceImports(newRoot)))
115-
{
116-
SyntaxNode systemNamespaceImport = generator.NamespaceImportDeclaration(nameof(System));
117-
newRoot = generator.AddNamespaceImports(newRoot, systemNamespaceImport);
118-
}
119-
120111
editor.ReplaceNode(root, newRoot);
121112
return editor.GetChangedDocument();
122113
}
@@ -140,7 +131,7 @@ private SyntaxNode ConvertOperandToArgument(in RequiredSymbols symbols, SyntaxGe
140131
invocationSyntax = generator.ReplaceNode(invocationSyntax, namedStartIndexArgument.Syntax, renamedArgumentSyntax);
141132
}
142133

143-
var asSpanInvocationSyntax = ReplaceInvocationMethodName(generator, invocationSyntax, AsSpanName);
134+
var asSpanInvocationSyntax = ReplaceInvocationMethodName(generator, invocationSyntax, AsSpanName).WithAddImportsAnnotation().WithAdditionalAnnotations(s_asSpanSymbolAnnotation);
144135
return generator.Argument(asSpanInvocationSyntax);
145136
}
146137
// Character literals become string literals.

src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/UseSpanBasedStringConcatTests.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,31 @@ public Task WithNonStringNonCharLiteralOperands_NoDiagnostic_VBAsync(string expr
761761
};
762762
return test.RunAsync();
763763
}
764+
765+
[Fact]
766+
public Task TestSystemImportedFromGlobalUsing()
767+
{
768+
var test = new VerifyCS.Test
769+
{
770+
TestState =
771+
{
772+
Sources =
773+
{
774+
"global using System;", CSWithBody("var _ = [|foo + bar.Substring(1)|];"),
775+
},
776+
},
777+
FixedState =
778+
{
779+
Sources =
780+
{
781+
"global using System;", CSWithBody("var _ = string.Concat(foo, bar.AsSpan(1));"),
782+
},
783+
},
784+
ReferenceAssemblies = ReferenceAssemblies.Net.Net50,
785+
LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp10,
786+
};
787+
return test.RunAsync();
788+
}
764789
#endregion
765790

766791
#region Helpers

src/NetAnalyzers/VisualBasic/Microsoft.NetCore.Analyzers/Runtime/BasicUseSpanBasedStringConcat.Fixer.vb

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -22,35 +22,6 @@ Namespace Microsoft.NetCore.VisualBasic.Analyzers.Runtime
2222
Return invocationSyntax.ReplaceNode(oldNameSyntax, newNameSyntax)
2323
End Function
2424

25-
Private Protected Overrides Function IsSystemNamespaceImported(project As Project, namespaceImports As IReadOnlyList(Of SyntaxNode)) As Boolean
26-
27-
Dim options = DirectCast(project.CompilationOptions, VisualBasicCompilationOptions)
28-
If options.GlobalImports.Any(Function(x) String.Compare(x.Name, NameOf(System), StringComparison.OrdinalIgnoreCase) = 0) Then
29-
Return True
30-
End If
31-
32-
For Each node As SyntaxNode In namespaceImports
33-
Dim importsStatement = TryCast(node, ImportsStatementSyntax)
34-
If importsStatement Is Nothing Then
35-
Continue For
36-
End If
37-
38-
For Each importsClause As ImportsClauseSyntax In importsStatement.ImportsClauses
39-
Dim simpleClause = TryCast(importsClause, SimpleImportsClauseSyntax)
40-
Dim identifierName = TryCast(simpleClause?.Name, IdentifierNameSyntax)
41-
If identifierName Is Nothing Then
42-
Continue For
43-
End If
44-
45-
If identifierName.Identifier.ValueText = NameOf(System) Then
46-
Return True
47-
End If
48-
Next
49-
Next
50-
51-
Return False
52-
End Function
53-
5425
Private Protected Overrides Function WalkDownBuiltInImplicitConversionOnConcatOperand(operand As IOperation) As IOperation
5526

5627
Return UseSpanBasedStringConcat.BasicWalkDownBuiltInImplicitConversionOnConcatOperand(operand)

0 commit comments

Comments
 (0)