Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

#nullable disable

namespace StyleCop.Analyzers.Test.CSharp10.OrderingRules
{
using System.Threading;
Expand Down Expand Up @@ -40,5 +38,30 @@ namespace TestNamespace;

await VerifyCSharpFixAsync(testCode, expectedResults, fixedTestCode, CancellationToken.None).ConfigureAwait(false);
}

[Theory]
[InlineData("")]
[InlineData("\n")]
[InlineData("// A comment.\n")]
[WorkItem(3875, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3875")]
public async Task TestOnlyGlobalUsingStatementInFileAsync(string leadingTrivia)
{
var testCode = $@"{leadingTrivia}global using System;";

await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
}

[Fact]
[WorkItem(3875, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3875")]
public async Task TestGlobalUsingStatementInFileWithNamespaceAsync()
{
var testCode = @"[|global using System;|]

namespace TestNamespace
{
}";

await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

#nullable disable

namespace StyleCop.Analyzers.Test.CSharp10.OrderingRules
{
using System.Threading;
Expand Down Expand Up @@ -36,5 +34,17 @@ namespace TestNamespace;

await VerifyCSharpFixAsync(testCode, expectedResults, fixedTestCode, CancellationToken.None).ConfigureAwait(false);
}

[Theory]
[InlineData("")]
[InlineData("\n")]
[InlineData("// A comment.\n")]
[WorkItem(3875, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3875")]
public async Task TestOnlyGlobalUsingStatementInFileAsync(string leadingTrivia)
{
var testCode = $@"{leadingTrivia}global using System;";

await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

#nullable disable

namespace StyleCop.Analyzers.Test.CSharp10.OrderingRules
{
using System.Threading;
Expand Down Expand Up @@ -41,5 +39,17 @@ namespace TestNamespace;

await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
}

[Theory]
[InlineData("")]
[InlineData("\n")]
[InlineData("// A comment.\n")]
[WorkItem(3875, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3875")]
public async Task TestOnlyGlobalUsingStatementInFileAsync(string leadingTrivia)
{
var testCode = $@"{leadingTrivia}global using System;";

await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

namespace StyleCop.Analyzers.Lightup
{
using System;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;

internal static class UsingDirectiveSyntaxExtensions
{
private static readonly Func<UsingDirectiveSyntax, SyntaxToken> GlobalKeywordAccessor;
private static readonly Func<UsingDirectiveSyntax, SyntaxToken, UsingDirectiveSyntax> WithGlobalKeywordAccessor;

static UsingDirectiveSyntaxExtensions()
{
GlobalKeywordAccessor = LightupHelpers.CreateSyntaxPropertyAccessor<UsingDirectiveSyntax, SyntaxToken>(typeof(UsingDirectiveSyntax), nameof(GlobalKeyword));
WithGlobalKeywordAccessor = LightupHelpers.CreateSyntaxWithPropertyAccessor<UsingDirectiveSyntax, SyntaxToken>(typeof(UsingDirectiveSyntax), nameof(GlobalKeyword));
}

public static SyntaxToken GlobalKeyword(this UsingDirectiveSyntax syntax)
{
return GlobalKeywordAccessor(syntax);
}

public static UsingDirectiveSyntax WithGlobalKeyword(this UsingDirectiveSyntax syntax, SyntaxToken globalKeyword)
{
return WithGlobalKeywordAccessor(syntax, globalKeyword);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ private static void HandleCompilationUnit(SyntaxNodeAnalysisContext context, Sty
CompilationUnitSyntax syntax = (CompilationUnitSyntax)context.Node;

List<SyntaxNode> usingDirectives = new List<SyntaxNode>();
bool containsOnlyGlobalUsingDirectives = true;
foreach (SyntaxNode child in syntax.ChildNodes())
{
switch (child.Kind())
Expand All @@ -238,16 +239,25 @@ private static void HandleCompilationUnit(SyntaxNodeAnalysisContext context, Sty

case SyntaxKind.UsingDirective:
usingDirectives.Add(child);
bool isGlobalUsing = ((UsingDirectiveSyntax)child).GlobalKeyword().IsKind(SyntaxKind.GlobalKeyword);
containsOnlyGlobalUsingDirectives = containsOnlyGlobalUsingDirectives && isGlobalUsing;
continue;

case SyntaxKind.ExternAliasDirective:
case SyntaxKind.NamespaceDeclaration:
case SyntaxKindEx.FileScopedNamespaceDeclaration:
case SyntaxKind.ExternAliasDirective:
default:
containsOnlyGlobalUsingDirectives = false;
continue;
}
}

if (containsOnlyGlobalUsingDirectives)
{
// Suppress SA1200 if file only contains global using directives
return;
}

foreach (var directive in usingDirectives)
{
// Using directive should appear within a namespace declaration
Expand Down