Improve highlight locations of some BizHawk.Analyzer diagnostics
This commit is contained in:
parent
df11522190
commit
ca0ddeffef
|
@ -39,6 +39,50 @@ public static class DDExtensions
|
||||||
properties: null,
|
properties: null,
|
||||||
messageArgs: messageArgs));
|
messageArgs: messageArgs));
|
||||||
|
|
||||||
|
[MI(AggressiveInlining)]
|
||||||
|
public static void ReportAt(
|
||||||
|
this DD diag,
|
||||||
|
Location location,
|
||||||
|
DiagnosticSeverity effectiveSeverity,
|
||||||
|
OAC ctx,
|
||||||
|
string message)
|
||||||
|
=> diag.ReportAt(location, effectiveSeverity, ctx, [ message ]);
|
||||||
|
|
||||||
|
[MI(AggressiveInlining)]
|
||||||
|
public static void ReportAt(
|
||||||
|
this DD diag,
|
||||||
|
Location location,
|
||||||
|
DiagnosticSeverity effectiveSeverity,
|
||||||
|
SNAC ctx,
|
||||||
|
string message)
|
||||||
|
=> diag.ReportAt(location, effectiveSeverity, ctx, [ message ]);
|
||||||
|
|
||||||
|
[MI(AggressiveInlining)]
|
||||||
|
public static void ReportAt(
|
||||||
|
this DD diag,
|
||||||
|
Location location,
|
||||||
|
bool isErrorSeverity,
|
||||||
|
OAC ctx,
|
||||||
|
object?[]? messageArgs = null)
|
||||||
|
=> diag.ReportAt(
|
||||||
|
location,
|
||||||
|
isErrorSeverity ? DiagnosticSeverity.Error : DiagnosticSeverity.Warning,
|
||||||
|
ctx,
|
||||||
|
messageArgs: messageArgs);
|
||||||
|
|
||||||
|
[MI(AggressiveInlining)]
|
||||||
|
public static void ReportAt(
|
||||||
|
this DD diag,
|
||||||
|
Location location,
|
||||||
|
bool isErrorSeverity,
|
||||||
|
SNAC ctx,
|
||||||
|
object?[]? messageArgs = null)
|
||||||
|
=> diag.ReportAt(
|
||||||
|
location,
|
||||||
|
isErrorSeverity ? DiagnosticSeverity.Error : DiagnosticSeverity.Warning,
|
||||||
|
ctx,
|
||||||
|
messageArgs: messageArgs);
|
||||||
|
|
||||||
[MI(AggressiveInlining)]
|
[MI(AggressiveInlining)]
|
||||||
public static void ReportAt(this DD diag, Location location, OAC ctx, object?[]? messageArgs = null)
|
public static void ReportAt(this DD diag, Location location, OAC ctx, object?[]? messageArgs = null)
|
||||||
=> ctx.ReportDiagnostic(Diagnostic.Create(diag, location, messageArgs: messageArgs));
|
=> ctx.ReportDiagnostic(Diagnostic.Create(diag, location, messageArgs: messageArgs));
|
||||||
|
@ -47,6 +91,14 @@ public static class DDExtensions
|
||||||
public static void ReportAt(this DD diag, Location location, SNAC ctx, object?[]? messageArgs = null)
|
public static void ReportAt(this DD diag, Location location, SNAC ctx, object?[]? messageArgs = null)
|
||||||
=> ctx.ReportDiagnostic(Diagnostic.Create(diag, location, messageArgs: messageArgs));
|
=> ctx.ReportDiagnostic(Diagnostic.Create(diag, location, messageArgs: messageArgs));
|
||||||
|
|
||||||
|
[MI(AggressiveInlining)]
|
||||||
|
public static void ReportAt(this DD diag, Location location, OAC ctx, string message)
|
||||||
|
=> diag.ReportAt(location, ctx, [ message ]);
|
||||||
|
|
||||||
|
[MI(AggressiveInlining)]
|
||||||
|
public static void ReportAt(this DD diag, Location location, SNAC ctx, string message)
|
||||||
|
=> diag.ReportAt(location, ctx, [ message ]);
|
||||||
|
|
||||||
[MI(AggressiveInlining)]
|
[MI(AggressiveInlining)]
|
||||||
public static void ReportAt(
|
public static void ReportAt(
|
||||||
this DD diag,
|
this DD diag,
|
||||||
|
@ -123,6 +175,40 @@ public static class DDExtensions
|
||||||
public static void ReportAt(this DD diag, SyntaxNode location, SNAC ctx, string message)
|
public static void ReportAt(this DD diag, SyntaxNode location, SNAC ctx, string message)
|
||||||
=> diag.ReportAt(location, ctx, [ message ]);
|
=> diag.ReportAt(location, ctx, [ message ]);
|
||||||
|
|
||||||
|
[MI(AggressiveInlining)]
|
||||||
|
public static void ReportAt(
|
||||||
|
this DD diag,
|
||||||
|
SyntaxToken location,
|
||||||
|
DiagnosticSeverity effectiveSeverity,
|
||||||
|
OAC ctx,
|
||||||
|
string message)
|
||||||
|
=> diag.ReportAt(location.GetLocation(), effectiveSeverity, ctx, message);
|
||||||
|
|
||||||
|
[MI(AggressiveInlining)]
|
||||||
|
public static void ReportAt(
|
||||||
|
this DD diag,
|
||||||
|
SyntaxToken location,
|
||||||
|
DiagnosticSeverity effectiveSeverity,
|
||||||
|
SNAC ctx,
|
||||||
|
string message)
|
||||||
|
=> diag.ReportAt(location.GetLocation(), effectiveSeverity, ctx, message);
|
||||||
|
|
||||||
|
[MI(AggressiveInlining)]
|
||||||
|
public static void ReportAt(this DD diag, SyntaxToken location, OAC ctx, object?[]? messageArgs = null)
|
||||||
|
=> diag.ReportAt(location.GetLocation(), ctx, messageArgs);
|
||||||
|
|
||||||
|
[MI(AggressiveInlining)]
|
||||||
|
public static void ReportAt(this DD diag, SyntaxToken location, SNAC ctx, object?[]? messageArgs = null)
|
||||||
|
=> diag.ReportAt(location.GetLocation(), ctx, messageArgs);
|
||||||
|
|
||||||
|
[MI(AggressiveInlining)]
|
||||||
|
public static void ReportAt(this DD diag, SyntaxToken location, OAC ctx, string message)
|
||||||
|
=> diag.ReportAt(location, ctx, [ message ]);
|
||||||
|
|
||||||
|
[MI(AggressiveInlining)]
|
||||||
|
public static void ReportAt(this DD diag, SyntaxToken location, SNAC ctx, string message)
|
||||||
|
=> diag.ReportAt(location, ctx, [ message ]);
|
||||||
|
|
||||||
[MI(AggressiveInlining)]
|
[MI(AggressiveInlining)]
|
||||||
public static void ReportAt(
|
public static void ReportAt(
|
||||||
this DD diag,
|
this DD diag,
|
||||||
|
|
|
@ -90,6 +90,19 @@ public static class RoslynUtils
|
||||||
public static bool IsEmpty(this SyntaxToken token)
|
public static bool IsEmpty(this SyntaxToken token)
|
||||||
=> token.ToString().Length is 0;
|
=> token.ToString().Length is 0;
|
||||||
|
|
||||||
|
public static Location LocWithoutReceiver(this InvocationExpressionSyntax ies)
|
||||||
|
{
|
||||||
|
var location = ies.GetLocation();
|
||||||
|
if (ies.Expression is MemberAccessExpressionSyntax maes)
|
||||||
|
{
|
||||||
|
location = Location.Create(location.SourceTree!, location.SourceSpan.Slice(maes.Expression.Span.Length));
|
||||||
|
}
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Location LocWithoutReceiver(this IInvocationOperation operation)
|
||||||
|
=> ((InvocationExpressionSyntax) operation.Syntax).LocWithoutReceiver();
|
||||||
|
|
||||||
public static bool Matches(this ISymbol expected, ISymbol? actual)
|
public static bool Matches(this ISymbol expected, ISymbol? actual)
|
||||||
=> SymbolEqualityComparer.Default.Equals(expected, actual);
|
=> SymbolEqualityComparer.Default.Equals(expected, actual);
|
||||||
|
|
||||||
|
@ -118,4 +131,10 @@ public static class RoslynUtils
|
||||||
INamedTypeSymbol targetAttrSym,
|
INamedTypeSymbol targetAttrSym,
|
||||||
SyntaxNodeAnalysisContext snac)
|
SyntaxNodeAnalysisContext snac)
|
||||||
=> list.Matching(targetAttrSym, snac.SemanticModel, snac.CancellationToken);
|
=> list.Matching(targetAttrSym, snac.SemanticModel, snac.CancellationToken);
|
||||||
|
|
||||||
|
public static TextSpan Slice(this TextSpan span, int start)
|
||||||
|
=> TextSpan.FromBounds(start: span.Start + start, end: span.End);
|
||||||
|
|
||||||
|
public static TextSpan Slice(this TextSpan span, int start, int length)
|
||||||
|
=> new(start: span.Start + start, length: length);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@ public sealed class DefineCheckedOpAnalyzer : DiagnosticAnalyzer
|
||||||
obsoleteAttrSym ??= snac.Compilation.GetTypeByMetadataName("System.ObsoleteAttribute")!;
|
obsoleteAttrSym ??= snac.Compilation.GetTypeByMetadataName("System.ObsoleteAttribute")!;
|
||||||
void FindCounterpartAndMaybeReport<T>(
|
void FindCounterpartAndMaybeReport<T>(
|
||||||
T declSyn,
|
T declSyn,
|
||||||
|
SyntaxToken operatorTkn,
|
||||||
SyntaxList<AttributeListSyntax> attrLists,
|
SyntaxList<AttributeListSyntax> attrLists,
|
||||||
string checkedName,
|
string checkedName,
|
||||||
Func<T, string> getMethodName)
|
Func<T, string> getMethodName)
|
||||||
|
@ -54,11 +55,11 @@ public sealed class DefineCheckedOpAnalyzer : DiagnosticAnalyzer
|
||||||
.Any(syn => checkedName.Equals(getMethodName(syn), StringComparison.Ordinal));
|
.Any(syn => checkedName.Equals(getMethodName(syn), StringComparison.Ordinal));
|
||||||
if (!hasCheckedCounterpart)
|
if (!hasCheckedCounterpart)
|
||||||
{
|
{
|
||||||
DiagDefineCheckedOp.ReportAt(declSyn, snac, ERR_MSG_MAKE_CHECKED);
|
DiagDefineCheckedOp.ReportAt(operatorTkn, snac, ERR_MSG_MAKE_CHECKED);
|
||||||
}
|
}
|
||||||
else if (!attrLists.Matching(obsoleteAttrSym, snac).Any())
|
else if (!attrLists.Matching(obsoleteAttrSym, snac).Any())
|
||||||
{
|
{
|
||||||
DiagDefineCheckedOp.ReportAt(declSyn, DiagnosticSeverity.Warning, snac, ERR_MSG_DEPRECATE);
|
DiagDefineCheckedOp.ReportAt(operatorTkn, DiagnosticSeverity.Warning, snac, ERR_MSG_DEPRECATE);
|
||||||
}
|
}
|
||||||
// else usage is correct
|
// else usage is correct
|
||||||
}
|
}
|
||||||
|
@ -69,6 +70,7 @@ public sealed class DefineCheckedOpAnalyzer : DiagnosticAnalyzer
|
||||||
{
|
{
|
||||||
FindCounterpartAndMaybeReport(
|
FindCounterpartAndMaybeReport(
|
||||||
cods,
|
cods,
|
||||||
|
cods.OperatorKeyword,
|
||||||
cods.AttributeLists,
|
cods.AttributeLists,
|
||||||
checkedName,
|
checkedName,
|
||||||
RoslynUtils.GetMethodName);
|
RoslynUtils.GetMethodName);
|
||||||
|
@ -79,6 +81,7 @@ public sealed class DefineCheckedOpAnalyzer : DiagnosticAnalyzer
|
||||||
{
|
{
|
||||||
FindCounterpartAndMaybeReport(
|
FindCounterpartAndMaybeReport(
|
||||||
ods,
|
ods,
|
||||||
|
ods.OperatorKeyword,
|
||||||
ods.AttributeLists,
|
ods.AttributeLists,
|
||||||
checkedName1,
|
checkedName1,
|
||||||
RoslynUtils.GetMethodName);
|
RoslynUtils.GetMethodName);
|
||||||
|
|
|
@ -48,12 +48,12 @@ public sealed class FeatureNotImplementedAnalyzer : DiagnosticAnalyzer
|
||||||
void CheckBlockBody(BlockSyntax bs)
|
void CheckBlockBody(BlockSyntax bs)
|
||||||
{
|
{
|
||||||
if (bs.Statements is [ ThrowStatementSyntax tss ]) MaybeReportFor(snac.SemanticModel.GetThrownExceptionType(tss), tss);
|
if (bs.Statements is [ ThrowStatementSyntax tss ]) MaybeReportFor(snac.SemanticModel.GetThrownExceptionType(tss), tss);
|
||||||
else DiagShouldThrowNIE.ReportAt(bs.Parent!, snac, ERR_MSG_DOES_NOT_THROW);
|
else DiagShouldThrowNIE.ReportAt(bs, snac, ERR_MSG_DOES_NOT_THROW);
|
||||||
}
|
}
|
||||||
void CheckExprBody(ArrowExpressionClauseSyntax aecs)
|
void CheckExprBody(ArrowExpressionClauseSyntax aecs)
|
||||||
{
|
{
|
||||||
if (aecs.Expression is ThrowExpressionSyntax tes) MaybeReportFor(snac.SemanticModel.GetThrownExceptionType(tes), tes);
|
if (aecs.Expression is ThrowExpressionSyntax tes) MaybeReportFor(snac.SemanticModel.GetThrownExceptionType(tes), tes);
|
||||||
else DiagShouldThrowNIE.ReportAt(aecs.Parent!, snac, ERR_MSG_DOES_NOT_THROW);
|
else DiagShouldThrowNIE.ReportAt(aecs, snac, ERR_MSG_DOES_NOT_THROW);
|
||||||
}
|
}
|
||||||
void CheckAccessor(AccessorDeclarationSyntax ads)
|
void CheckAccessor(AccessorDeclarationSyntax ads)
|
||||||
{
|
{
|
||||||
|
|
|
@ -48,7 +48,7 @@ public sealed class FirstOrDefaultOnStructAnalyzer : DiagnosticAnalyzer
|
||||||
IArrayTypeSymbol ats => ats.ElementType,
|
IArrayTypeSymbol ats => ats.ElementType,
|
||||||
_ => throw HawkSourceAnalyzer.ReportWTF(receiverExpr, oac, message: $"[{nameof(FirstOrDefaultOnStructAnalyzer)}] receiver parameter's effective type was of an unexpected kind (neither class/struct nor array): {receiverExprType.GetType().FullName}")
|
_ => throw HawkSourceAnalyzer.ReportWTF(receiverExpr, oac, message: $"[{nameof(FirstOrDefaultOnStructAnalyzer)}] receiver parameter's effective type was of an unexpected kind (neither class/struct nor array): {receiverExprType.GetType().FullName}")
|
||||||
};
|
};
|
||||||
if (collectionElemType.IsValueType) DiagUseFirstOrNull.ReportAt(operation, oac);
|
if (collectionElemType.IsValueType) DiagUseFirstOrNull.ReportAt(operation.LocWithoutReceiver(), oac);
|
||||||
},
|
},
|
||||||
OperationKind.Invocation);
|
OperationKind.Invocation);
|
||||||
});
|
});
|
||||||
|
|
|
@ -158,7 +158,15 @@ public class HawkSourceAnalyzer : DiagnosticAnalyzer
|
||||||
void MaybeReportListExprSpacing(SyntaxNode listSyn, string? message)
|
void MaybeReportListExprSpacing(SyntaxNode listSyn, string? message)
|
||||||
{
|
{
|
||||||
if (message is null) return;
|
if (message is null) return;
|
||||||
DiagListExprSpacing.ReportAt(listSyn, snac, message);
|
var location = listSyn.GetLocation();
|
||||||
|
TextSpan? slice = message switch
|
||||||
|
{
|
||||||
|
ERR_MSG_LIST_EXPR_END => location.SourceSpan.Slice(start: location.SourceSpan.Length - 1),
|
||||||
|
ERR_MSG_LIST_EXPR_START => location.SourceSpan.Slice(start: 0, length: 1),
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
if (slice is not null) location = Location.Create(location.SourceTree!, slice.Value);
|
||||||
|
DiagListExprSpacing.ReportAt(location, snac, message);
|
||||||
}
|
}
|
||||||
switch (snac.Node)
|
switch (snac.Node)
|
||||||
{
|
{
|
||||||
|
@ -179,7 +187,8 @@ public class HawkSourceAnalyzer : DiagnosticAnalyzer
|
||||||
CheckSpacingInList(ces.Elements, ces.OpenBracketToken, ces.ToString));
|
CheckSpacingInList(ces.Elements, ces.OpenBracketToken, ces.ToString));
|
||||||
break;
|
break;
|
||||||
case InterpolatedStringExpressionSyntax ises:
|
case InterpolatedStringExpressionSyntax ises:
|
||||||
if (ises.StringStartToken.Text[0] is '@') DiagInterpStringIsDollarAt.ReportAt(ises, snac);
|
var interpTkn = ises.StringStartToken;
|
||||||
|
if (interpTkn.Text[0] is '@') DiagInterpStringIsDollarAt.ReportAt(interpTkn, snac);
|
||||||
break;
|
break;
|
||||||
case ListPatternSyntax lps:
|
case ListPatternSyntax lps:
|
||||||
MaybeReportListExprSpacing(
|
MaybeReportListExprSpacing(
|
||||||
|
@ -190,7 +199,7 @@ public class HawkSourceAnalyzer : DiagnosticAnalyzer
|
||||||
DiagNoQueryExpression.ReportAt(snac.Node, snac);
|
DiagNoQueryExpression.ReportAt(snac.Node, snac);
|
||||||
break;
|
break;
|
||||||
case RecordDeclarationSyntax rds when rds.ClassOrStructKeyword.ToString() is not "class": // `record struct`s don't use this kind
|
case RecordDeclarationSyntax rds when rds.ClassOrStructKeyword.ToString() is not "class": // `record struct`s don't use this kind
|
||||||
DiagRecordImplicitlyRefType.ReportAt(rds, snac);
|
DiagRecordImplicitlyRefType.ReportAt(rds.Keyword, snac);
|
||||||
break;
|
break;
|
||||||
case SwitchExpressionArmSyntax { WhenClause: null, Pattern: DiscardPatternSyntax, Expression: ThrowExpressionSyntax tes }:
|
case SwitchExpressionArmSyntax { WhenClause: null, Pattern: DiscardPatternSyntax, Expression: ThrowExpressionSyntax tes }:
|
||||||
var thrownExceptionType = snac.SemanticModel.GetThrownExceptionType(tes);
|
var thrownExceptionType = snac.SemanticModel.GetThrownExceptionType(tes);
|
||||||
|
|
|
@ -119,7 +119,11 @@ public sealed class LINQOnStringsAnalyzer : DiagnosticAnalyzer
|
||||||
: "Use `str.Contains(c.ToString())`";
|
: "Use `str.Contains(c.ToString())`";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DiagLINQOnStrings.ReportAt(operation, level, oac, string.Format(msgFmtStr, receiverExpr.Syntax));
|
DiagLINQOnStrings.ReportAt(
|
||||||
|
operation.LocWithoutReceiver(),
|
||||||
|
level,
|
||||||
|
oac,
|
||||||
|
string.Format(msgFmtStr, receiverExpr.Syntax));
|
||||||
},
|
},
|
||||||
OperationKind.Invocation);
|
OperationKind.Invocation);
|
||||||
});
|
});
|
||||||
|
|
|
@ -39,7 +39,10 @@ public sealed class TryGetValueImplicitDiscardAnalyzer : DiagnosticAnalyzer
|
||||||
var calledSym = operation.TargetMethod.ConstructedFrom;
|
var calledSym = operation.TargetMethod.ConstructedFrom;
|
||||||
if (calledSym.Name is STR_TGV)
|
if (calledSym.Name is STR_TGV)
|
||||||
{
|
{
|
||||||
DiagUncheckedTryGetValue.ReportAt(operation, isErrorSeverity: IsBCLTryGetValue(calledSym), oac);
|
DiagUncheckedTryGetValue.ReportAt(
|
||||||
|
operation.LocWithoutReceiver(),
|
||||||
|
isErrorSeverity: IsBCLTryGetValue(calledSym),
|
||||||
|
oac);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
OperationKind.Invocation);
|
OperationKind.Invocation);
|
||||||
|
|
|
@ -19,23 +19,23 @@ public sealed class DefineCheckedOpAnalyzerTests
|
||||||
public struct GF7 {
|
public struct GF7 {
|
||||||
private static readonly int[] Inverses = [ -1, 1, 4, 5, 2, 3, 6 ];
|
private static readonly int[] Inverses = [ -1, 1, 4, 5, 2, 3, 6 ];
|
||||||
public static GF7 operator checked -(GF7 x) => new(-x._value); // the most useless but here for completeness
|
public static GF7 operator checked -(GF7 x) => new(-x._value); // the most useless but here for completeness
|
||||||
{|BHI1300:public static GF7 operator /*unchecked*/ -(GF7 x) => new(-x._value % 7);|}
|
public static GF7 {|BHI1300:operator|} /*unchecked*/ -(GF7 x) => new(-x._value % 7);
|
||||||
public static GF7 operator checked ++(GF7 x) => new(x._value + 1);
|
public static GF7 operator checked ++(GF7 x) => new(x._value + 1);
|
||||||
{|BHI1300:public static GF7 operator /*unchecked*/ ++(GF7 x) => new((x._value + 1) % 7);|}
|
public static GF7 {|BHI1300:operator|} /*unchecked*/ ++(GF7 x) => new((x._value + 1) % 7);
|
||||||
public static GF7 operator checked --(GF7 x) => new(x._value - 1);
|
public static GF7 operator checked --(GF7 x) => new(x._value - 1);
|
||||||
{|BHI1300:public static GF7 operator /*unchecked*/ --(GF7 x) => new((x._value - 1) % 7);|}
|
public static GF7 {|BHI1300:operator|} /*unchecked*/ --(GF7 x) => new((x._value - 1) % 7);
|
||||||
public static GF7 operator checked +(GF7 x, GF7 y) => new(x._value + y._value);
|
public static GF7 operator checked +(GF7 x, GF7 y) => new(x._value + y._value);
|
||||||
{|BHI1300:public static GF7 operator /*unchecked*/ +(GF7 x, GF7 y) => new((x._value + y._value) % 7);|}
|
public static GF7 {|BHI1300:operator|} /*unchecked*/ +(GF7 x, GF7 y) => new((x._value + y._value) % 7);
|
||||||
public static GF7 operator checked +(GF7 x, int y) => new(x._value + y);
|
public static GF7 operator checked +(GF7 x, int y) => new(x._value + y);
|
||||||
{|BHI1300:public static GF7 operator /*unchecked*/ +(GF7 x, int y) => new((x._value + y) % 7);|}
|
public static GF7 {|BHI1300:operator|} /*unchecked*/ +(GF7 x, int y) => new((x._value + y) % 7);
|
||||||
public static GF7 operator checked -(GF7 minuend, int subtrahend) => new(minuend._value - subtrahend);
|
public static GF7 operator checked -(GF7 minuend, int subtrahend) => new(minuend._value - subtrahend);
|
||||||
{|BHI1300:public static GF7 operator /*unchecked*/ -(GF7 minuend, int subtrahend) => new((minuend._value - subtrahend) % 7);|}
|
public static GF7 {|BHI1300:operator|} /*unchecked*/ -(GF7 minuend, int subtrahend) => new((minuend._value - subtrahend) % 7);
|
||||||
public static GF7 operator checked *(GF7 x, int y) => new(x._value * y);
|
public static GF7 operator checked *(GF7 x, int y) => new(x._value * y);
|
||||||
{|BHI1300:public static GF7 operator /*unchecked*/ *(GF7 x, int y) => new((x._value * y) % 7);|}
|
public static GF7 {|BHI1300:operator|} /*unchecked*/ *(GF7 x, int y) => new((x._value * y) % 7);
|
||||||
public static GF7 operator checked /(GF7 dividend, GF7 divisor) => new((dividend._value * Inverses[divisor._value]) % 7);
|
public static GF7 operator checked /(GF7 dividend, GF7 divisor) => new((dividend._value * Inverses[divisor._value]) % 7);
|
||||||
{|BHI1300:public static GF7 operator /*unchecked*/ /(GF7 dividend, GF7 divisor) => divisor._value is 0 ? default : new((dividend._value * Inverses[divisor._value]) % 7);|}
|
public static GF7 {|BHI1300:operator|} /*unchecked*/ /(GF7 dividend, GF7 divisor) => divisor._value is 0 ? default : new((dividend._value * Inverses[divisor._value]) % 7);
|
||||||
public static explicit operator checked GF7(int n) => new(n);
|
public static explicit operator checked GF7(int n) => new(n);
|
||||||
{|BHI1300:public static explicit operator /*unchecked*/ GF7(int n) => new(n % 7);|}
|
public static explicit {|BHI1300:operator|} /*unchecked*/ GF7(int n) => new(n % 7);
|
||||||
private byte _value;
|
private byte _value;
|
||||||
public byte Value {
|
public byte Value {
|
||||||
get => _value;
|
get => _value;
|
||||||
|
@ -55,15 +55,15 @@ public sealed class DefineCheckedOpAnalyzerTests
|
||||||
using System;
|
using System;
|
||||||
public struct GF7 {
|
public struct GF7 {
|
||||||
private static readonly int[] Inverses = [ -1, 1, 4, 5, 2, 3, 6 ];
|
private static readonly int[] Inverses = [ -1, 1, 4, 5, 2, 3, 6 ];
|
||||||
{|BHI1300:public static GF7 operator -(GF7 x) => new(-x._value % 7);|}
|
public static GF7 {|BHI1300:operator|} -(GF7 x) => new(-x._value % 7);
|
||||||
{|BHI1300:public static GF7 operator ++(GF7 x) => new((x._value + 1) % 7);|}
|
public static GF7 {|BHI1300:operator|} ++(GF7 x) => new((x._value + 1) % 7);
|
||||||
{|BHI1300:public static GF7 operator --(GF7 x) => new((x._value - 1) % 7);|}
|
public static GF7 {|BHI1300:operator|} --(GF7 x) => new((x._value - 1) % 7);
|
||||||
{|BHI1300:public static GF7 operator +(GF7 x, GF7 y) => new((x._value + y._value) % 7);|}
|
public static GF7 {|BHI1300:operator|} +(GF7 x, GF7 y) => new((x._value + y._value) % 7);
|
||||||
{|BHI1300:public static GF7 operator +(GF7 x, int y) => new((x._value + y) % 7);|}
|
public static GF7 {|BHI1300:operator|} +(GF7 x, int y) => new((x._value + y) % 7);
|
||||||
{|BHI1300:public static GF7 operator -(GF7 minuend, int subtrahend) => new((minuend._value - subtrahend) % 7);|}
|
public static GF7 {|BHI1300:operator|} -(GF7 minuend, int subtrahend) => new((minuend._value - subtrahend) % 7);
|
||||||
{|BHI1300:public static GF7 operator *(GF7 x, int y) => new((x._value * y) % 7);|}
|
public static GF7 {|BHI1300:operator|} *(GF7 x, int y) => new((x._value * y) % 7);
|
||||||
{|BHI1300:public static GF7 operator /(GF7 dividend, GF7 divisor) => divisor._value is 0 ? default : new((dividend._value * Inverses[divisor._value]) % 7);|}
|
public static GF7 {|BHI1300:operator|} /(GF7 dividend, GF7 divisor) => divisor._value is 0 ? default : new((dividend._value * Inverses[divisor._value]) % 7);
|
||||||
{|BHI1300:public static explicit operator GF7(int n) => new(n % 7);|}
|
public static explicit {|BHI1300:operator|} GF7(int n) => new(n % 7);
|
||||||
private byte _value;
|
private byte _value;
|
||||||
public byte Value {
|
public byte Value {
|
||||||
get => _value;
|
get => _value;
|
||||||
|
|
|
@ -20,13 +20,13 @@ public sealed class FeatureNotImplementedAnalyzerTests
|
||||||
}
|
}
|
||||||
[FeatureNotImplemented] private static int Z()
|
[FeatureNotImplemented] private static int Z()
|
||||||
=> throw new NotImplementedException();
|
=> throw new NotImplementedException();
|
||||||
{|BHI3300:[FeatureNotImplemented] private static int A => default;|}
|
[FeatureNotImplemented] private static int A {|BHI3300:=> default|};
|
||||||
private static int B {
|
private static int B {
|
||||||
{|BHI3300:[FeatureNotImplemented] get => default;|}
|
[FeatureNotImplemented] get {|BHI3300:=> default|};
|
||||||
{|BHI3300:[FeatureNotImplemented] set => _ = value;|}
|
[FeatureNotImplemented] set {|BHI3300:=> _ = value|};
|
||||||
}
|
}
|
||||||
{|BHI3300:[FeatureNotImplemented] private static int C()
|
[FeatureNotImplemented] private static int C()
|
||||||
=> default;|}
|
{|BHI3300:=> default|};
|
||||||
// wrong exception type, same code but different message:
|
// wrong exception type, same code but different message:
|
||||||
[FeatureNotImplemented] private static int D => {|BHI3300:throw new InvalidOperationException()|};
|
[FeatureNotImplemented] private static int D => {|BHI3300:throw new InvalidOperationException()|};
|
||||||
private static int E {
|
private static int E {
|
||||||
|
|
|
@ -18,13 +18,13 @@ public sealed class FirstOrDefaultOnStructAnalyzerTests
|
||||||
private static string? Z()
|
private static string? Z()
|
||||||
=> new List<int> { 0x80, 0x20, 0x40 }.Select(static n => n.ToString()).FirstOrDefault();
|
=> new List<int> { 0x80, 0x20, 0x40 }.Select(static n => n.ToString()).FirstOrDefault();
|
||||||
private static int A()
|
private static int A()
|
||||||
=> {|BHI3100:new[] { 0x80, 0x20, 0x40 }.FirstOrDefault()|};
|
=> new[] { 0x80, 0x20, 0x40 }{|BHI3100:.FirstOrDefault()|};
|
||||||
private static int B()
|
private static int B()
|
||||||
=> {|BHI3100:new List<int> { 0x80, 0x20, 0x40 }.FirstOrDefault()|};
|
=> new List<int> { 0x80, 0x20, 0x40 }{|BHI3100:.FirstOrDefault()|};
|
||||||
private static int C()
|
private static int C()
|
||||||
=> {|BHI3100:new[] { 0x80, 0x20, 0x40 }.FirstOrDefault(static n => n.ToString().Length > 2)|};
|
=> new[] { 0x80, 0x20, 0x40 }{|BHI3100:.FirstOrDefault(static n => n.ToString().Length > 2)|};
|
||||||
private static int D()
|
private static int D()
|
||||||
=> {|BHI3100:new List<int> { 0x80, 0x20, 0x40 }.FirstOrDefault(static n => n.ToString().Length > 2)|};
|
=> new List<int> { 0x80, 0x20, 0x40 }{|BHI3100:.FirstOrDefault(static n => n.ToString().Length > 2)|};
|
||||||
}
|
}
|
||||||
namespace BizHawk.Common.CollectionExtensions {
|
namespace BizHawk.Common.CollectionExtensions {
|
||||||
public static class CollectionExtensions {} // Analyzer short-circuits if this doesn't exist, since that's where the extension lives
|
public static class CollectionExtensions {} // Analyzer short-circuits if this doesn't exist, since that's where the extension lives
|
||||||
|
|
|
@ -106,7 +106,7 @@ public sealed class HawkSourceAnalyzerTests
|
||||||
=> Verify.VerifyAnalyzerAsync("""
|
=> Verify.VerifyAnalyzerAsync("""
|
||||||
public static class Cases {
|
public static class Cases {
|
||||||
private static readonly int Z = $@"{0x100}".Length;
|
private static readonly int Z = $@"{0x100}".Length;
|
||||||
private static readonly int A = {|BHI1004:@$"{0x100}"|}.Length;
|
private static readonly int A = {|BHI1004:@$"|}{0x100}".Length;
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
|
|
||||||
|
@ -119,9 +119,9 @@ public sealed class HawkSourceAnalyzerTests
|
||||||
private static readonly int[] X = W ? [ ] : V;
|
private static readonly int[] X = W ? [ ] : V;
|
||||||
private static readonly int[] Y = [ 0x80, 0x20, 0x40 ];
|
private static readonly int[] Y = [ 0x80, 0x20, 0x40 ];
|
||||||
private static readonly bool Z = Y is [ _, > 20, .. ];
|
private static readonly bool Z = Y is [ _, > 20, .. ];
|
||||||
private static readonly int[] A = {|BHI1110:[0x80, 0x20, 0x40 ]|};
|
private static readonly int[] A = {|BHI1110:[|}0x80, 0x20, 0x40 ];
|
||||||
private static readonly bool B = A is {|BHI1110:[ _, > 20, ..]|};
|
private static readonly bool B = A is [ _, > 20, ..{|BHI1110:]|};
|
||||||
private static readonly bool C = A is {|BHI1110:[_, > 20, ..]|};
|
private static readonly bool C = A is [_, > 20, ..{|BHI1110:]|}; // the way this is written, it will flag end and then start
|
||||||
private static readonly int[] D = {|BHI1110:[]|};
|
private static readonly int[] D = {|BHI1110:[]|};
|
||||||
private static readonly bool E = D is {|BHI1110:[]|};
|
private static readonly bool E = D is {|BHI1110:[]|};
|
||||||
private static readonly int[] F = E ? {|BHI1110:[]|} : D;
|
private static readonly int[] F = E ? {|BHI1110:[]|} : D;
|
||||||
|
@ -133,7 +133,7 @@ public sealed class HawkSourceAnalyzerTests
|
||||||
=> Verify.VerifyAnalyzerAsync("""
|
=> Verify.VerifyAnalyzerAsync("""
|
||||||
internal record struct Y {}
|
internal record struct Y {}
|
||||||
internal record class Z {}
|
internal record class Z {}
|
||||||
{|BHI1130:internal record A {}|}
|
internal {|BHI1130:record|} A {}
|
||||||
""");
|
""");
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
|
|
|
@ -36,49 +36,49 @@ public sealed class LINQOnStringsAnalyzerTests
|
||||||
private static bool ZZ(string str)
|
private static bool ZZ(string str)
|
||||||
=> str.All(DummyPredicate);
|
=> str.All(DummyPredicate);
|
||||||
private static bool AA(string str)
|
private static bool AA(string str)
|
||||||
=> {|BHI3102:str.Any()|};
|
=> str{|BHI3102:.Any()|};
|
||||||
private static IEnumerable<char> AB(string str)
|
private static IEnumerable<char> AB(string str)
|
||||||
=> {|BHI3102:str.Append('.')|};
|
=> str{|BHI3102:.Append('.')|};
|
||||||
private static IEnumerable<char> AC(string str)
|
private static IEnumerable<char> AC(string str)
|
||||||
=> {|BHI3102:str.Concat("-_-")|};
|
=> str{|BHI3102:.Concat("-_-")|};
|
||||||
private static IEnumerable<char> AD(string str)
|
private static IEnumerable<char> AD(string str)
|
||||||
=> {|BHI3102:str.Concat(new[] { '-', '_', '-' })|};
|
=> str{|BHI3102:.Concat(new[] { '-', '_', '-' })|};
|
||||||
private static bool AE(string str)
|
private static bool AE(string str)
|
||||||
=> {|BHI3102:Enumerable.Contains(str, '.')|};
|
=> Enumerable{|BHI3102:.Contains(str, '.')|};
|
||||||
private static int AF(string str)
|
private static int AF(string str)
|
||||||
=> {|BHI3102:str.Count()|};
|
=> str{|BHI3102:.Count()|};
|
||||||
private static IEnumerable<char> AG(string str)
|
private static IEnumerable<char> AG(string str)
|
||||||
=> {|BHI3102:str.DefaultIfEmpty()|};
|
=> str{|BHI3102:.DefaultIfEmpty()|};
|
||||||
private static IEnumerable<char> AH(string str)
|
private static IEnumerable<char> AH(string str)
|
||||||
=> {|BHI3102:str.DefaultIfEmpty('.')|};
|
=> str{|BHI3102:.DefaultIfEmpty('.')|};
|
||||||
private static char AI(string str)
|
private static char AI(string str)
|
||||||
=> {|BHI3102:str.ElementAt(2)|};
|
=> str{|BHI3102:.ElementAt(2)|};
|
||||||
private static char AJ(string str)
|
private static char AJ(string str)
|
||||||
=> {|BHI3102:str.ElementAtOrDefault(2)|};
|
=> str{|BHI3102:.ElementAtOrDefault(2)|};
|
||||||
private static char AK(string str)
|
private static char AK(string str)
|
||||||
=> {|BHI3102:str.First()|};
|
=> str{|BHI3102:.First()|};
|
||||||
private static char AL(string str)
|
private static char AL(string str)
|
||||||
=> {|BHI3102:str.FirstOrDefault()|};
|
=> str{|BHI3102:.FirstOrDefault()|};
|
||||||
private static char AM(string str)
|
private static char AM(string str)
|
||||||
=> {|BHI3102:str.Last()|};
|
=> str{|BHI3102:.Last()|};
|
||||||
private static char AN(string str)
|
private static char AN(string str)
|
||||||
=> {|BHI3102:str.LastOrDefault()|};
|
=> str{|BHI3102:.LastOrDefault()|};
|
||||||
private static long AO(string str)
|
private static long AO(string str)
|
||||||
=> {|BHI3102:str.LongCount()|};
|
=> str{|BHI3102:.LongCount()|};
|
||||||
private static IEnumerable<char> AP(string str)
|
private static IEnumerable<char> AP(string str)
|
||||||
=> {|BHI3102:str.Prepend('.')|};
|
=> str{|BHI3102:.Prepend('.')|};
|
||||||
private static IEnumerable<char> AQ(string str)
|
private static IEnumerable<char> AQ(string str)
|
||||||
=> {|BHI3102:str.Reverse()|};
|
=> str{|BHI3102:.Reverse()|};
|
||||||
private static char AR(string str)
|
private static char AR(string str)
|
||||||
=> {|BHI3102:str.Single()|};
|
=> str{|BHI3102:.Single()|};
|
||||||
private static char AS(string str)
|
private static char AS(string str)
|
||||||
=> {|BHI3102:str.SingleOrDefault()|};
|
=> str{|BHI3102:.SingleOrDefault()|};
|
||||||
private static IEnumerable<char> AT(string str)
|
private static IEnumerable<char> AT(string str)
|
||||||
=> {|BHI3102:str.Skip(2)|};
|
=> str{|BHI3102:.Skip(2)|};
|
||||||
private static IEnumerable<char> AU(string str)
|
private static IEnumerable<char> AU(string str)
|
||||||
=> {|BHI3102:str.Take(2)|};
|
=> str{|BHI3102:.Take(2)|};
|
||||||
private static char[] AV(string str)
|
private static char[] AV(string str)
|
||||||
=> {|BHI3102:str.ToArray()|};
|
=> str{|BHI3102:.ToArray()|};
|
||||||
}
|
}
|
||||||
namespace BizHawk.Common.StringExtensions {
|
namespace BizHawk.Common.StringExtensions {
|
||||||
public static class StringExtensions {} // Analyzer does more checks if this exists
|
public static class StringExtensions {} // Analyzer does more checks if this exists
|
||||||
|
|
|
@ -23,13 +23,13 @@ public sealed class TryGetValueImplicitDiscardAnalyzerTests
|
||||||
private static void Z()
|
private static void Z()
|
||||||
=> _ = MakeDict().TryGetValue("z", out _);
|
=> _ = MakeDict().TryGetValue("z", out _);
|
||||||
private static void A()
|
private static void A()
|
||||||
=> {|BHI1200:MakeDict().TryGetValue("a", out _)|};
|
=> MakeDict(){|BHI1200:.TryGetValue("a", out _)|};
|
||||||
private static void B()
|
private static void B()
|
||||||
=> {|BHI1200:((IDictionary<string, int>) MakeDict()).TryGetValue("b", out _)|};
|
=> ((IDictionary<string, int>) MakeDict()){|BHI1200:.TryGetValue("b", out _)|};
|
||||||
private static void C()
|
private static void C()
|
||||||
=> {|BHI1200:((IReadOnlyDictionary<string, int>) MakeDict()).TryGetValue("c", out _)|};
|
=> ((IReadOnlyDictionary<string, int>) MakeDict()){|BHI1200:.TryGetValue("c", out _)|};
|
||||||
private static void D()
|
private static void D()
|
||||||
=> {|BHI1200:new CustomDict<string, int>().TryGetValue("d", out _)|};
|
=> new CustomDict<string, int>(){|BHI1200:.TryGetValue("d", out _)|};
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue