Skip to content

Commit

Permalink
Fix RCS1216 (#1094)
Browse files Browse the repository at this point in the history
Co-authored-by: Josef Pihrt <josef.pihrt@outlook.com>
  • Loading branch information
jamesHargreaves12 and josefpihrt authored Jun 22, 2023
1 parent 5751160 commit ab44361
Show file tree
Hide file tree
Showing 3 changed files with 469 additions and 99 deletions.
1 change: 1 addition & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Recognize more shapes of IAsyncEnumerable as being Async ([RCS1047](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1047.md)) ([#1084](https://github.com/josefpihrt/roslynator/pull/1084)).
- Fix [RCS1197](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1197.md) ([#1093](https://github.com/JosefPihrt/Roslynator/pull/1093)).
- Fix [RCS1056](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1056.md) ([#1096](https://github.com/JosefPihrt/Roslynator/pull/1096)).
- Fix [RCS1216](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1216.md) ([#1094](https://github.com/JosefPihrt/Roslynator/pull/1094)).

## [4.3.0] - 2023-04-24

Expand Down
122 changes: 23 additions & 99 deletions src/Analyzers/CSharp/Analysis/UnnecessaryUnsafeContextAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ private static void AnalyzeUnsafeStatement(SyntaxNodeAnalysisContext context)
if (!unsafeStatement.Block.Statements.Any())
return;

if (!ParentDeclarationsContainsUnsafeModifier(unsafeStatement))
if (!AncestorContainsUnsafeModifier(unsafeStatement.Parent))
return;

DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.UnnecessaryUnsafeContext, unsafeStatement.UnsafeKeyword);
Expand All @@ -68,26 +68,7 @@ private static void AnalyzeLocalFunctionStatement(SyntaxNodeAnalysisContext cont
{
var localFunctionStatement = (LocalFunctionStatementSyntax)context.Node;

SyntaxTokenList modifiers = localFunctionStatement.Modifiers;

int index = modifiers.IndexOf(SyntaxKind.UnsafeKeyword);

if (index == -1)
return;

SyntaxNode parent = localFunctionStatement.Parent;

SyntaxDebug.Assert(parent.IsKind(SyntaxKind.Block), parent);

if (parent is not BlockSyntax)
return;

parent = parent.Parent;

if (!ParentDeclarationsContainsUnsafeModifier(parent))
return;

DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.UnnecessaryUnsafeContext, modifiers[index]);
AnalyzeMemberDeclaration(context, localFunctionStatement, localFunctionStatement.Modifiers);
}

private static void AnalyzeTypeDeclaration(SyntaxNodeAnalysisContext context)
Expand Down Expand Up @@ -176,102 +157,45 @@ private static void AnalyzeIndexerDeclaration(SyntaxNodeAnalysisContext context)

private static void AnalyzeMemberDeclaration(
SyntaxNodeAnalysisContext context,
MemberDeclarationSyntax memberDeclaration,
SyntaxNode node,
SyntaxTokenList modifiers)
{
int index = modifiers.IndexOf(SyntaxKind.UnsafeKeyword);

if (index == -1)
return;

if (!ParentTypeDeclarationsContainsUnsafeModifier(memberDeclaration))
if (!AncestorContainsUnsafeModifier(node.Parent))
return;

DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.UnnecessaryUnsafeContext, modifiers[index]);
}

private static bool ParentDeclarationsContainsUnsafeModifier(UnsafeStatementSyntax unsafeStatement)
private static bool AncestorContainsUnsafeModifier(SyntaxNode node)
{
SyntaxNode parent = unsafeStatement.Parent;

while (parent is not null)
while (node is not null)
{
SyntaxKind kind = parent.Kind();

if (kind == SyntaxKind.UnsafeStatement)
{
return true;
}
else if (kind == SyntaxKind.LocalFunctionStatement)
switch (node)
{
break;
case UnsafeStatementSyntax:
return true;
case MemberDeclarationSyntax memberDeclarationSyntax:
{
if (memberDeclarationSyntax.Modifiers.Contains(SyntaxKind.UnsafeKeyword))
return true;

break;
}
case LocalFunctionStatementSyntax localFunctionStatement:
{
if (localFunctionStatement.Modifiers.Contains(SyntaxKind.UnsafeKeyword))
return true;

break;
}
}

if (parent is AccessorDeclarationSyntax)
{
parent = parent.Parent;

if (parent is AccessorListSyntax)
parent = parent.Parent;

break;
}

if (parent is MemberDeclarationSyntax)
break;

parent = parent.Parent;
}

return ParentDeclarationsContainsUnsafeModifier(parent);
}

private static bool ParentDeclarationsContainsUnsafeModifier(SyntaxNode node)
{
while (node.IsKind(SyntaxKind.LocalFunctionStatement))
{
var localFunction = (LocalFunctionStatementSyntax)node;

if (localFunction.Modifiers.Contains(SyntaxKind.UnsafeKeyword))
return true;

node = node.Parent;

SyntaxDebug.Assert(node.IsKind(SyntaxKind.Block), node);

if (!node.IsKind(SyntaxKind.Block))
break;

node = node.Parent;
}

SyntaxDebug.Assert(node is MemberDeclarationSyntax, node);

if (node is MemberDeclarationSyntax memberDeclaration)
{
if (SyntaxInfo.ModifierListInfo(memberDeclaration).IsUnsafe)
return true;

return ParentTypeDeclarationsContainsUnsafeModifier(memberDeclaration);
}

return false;
}

private static bool ParentTypeDeclarationsContainsUnsafeModifier(MemberDeclarationSyntax memberDeclaration)
{
SyntaxNode parent = memberDeclaration.Parent;

while (parent.IsKind(
SyntaxKind.ClassDeclaration,
SyntaxKind.StructDeclaration,
SyntaxKind.RecordStructDeclaration,
SyntaxKind.InterfaceDeclaration))
{
if (((TypeDeclarationSyntax)parent).Modifiers.Contains(SyntaxKind.UnsafeKeyword))
return true;

parent = parent.Parent;
}

return false;
Expand Down
Loading

0 comments on commit ab44361

Please sign in to comment.