From 1fb625dc42a7cf5fdf74329454bc3ecde806ae10 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 10 Apr 2018 18:23:08 -0400 Subject: fix some net field comparisons to null not flagged (#471) --- .../NetFieldAnalyzer.cs | 46 ++++++++++++---------- 1 file changed, 26 insertions(+), 20 deletions(-) (limited to 'src/SMAPI.ModBuildConfig.Analyzer/NetFieldAnalyzer.cs') diff --git a/src/SMAPI.ModBuildConfig.Analyzer/NetFieldAnalyzer.cs b/src/SMAPI.ModBuildConfig.Analyzer/NetFieldAnalyzer.cs index 2cb1ac4c..ae646fd8 100644 --- a/src/SMAPI.ModBuildConfig.Analyzer/NetFieldAnalyzer.cs +++ b/src/SMAPI.ModBuildConfig.Analyzer/NetFieldAnalyzer.cs @@ -230,10 +230,32 @@ namespace StardewModdingAPI.ModBuildConfig.Analyzer { try { - BinaryExpressionSyntax node = (BinaryExpressionSyntax)context.Node; - bool leftHasWarning = this.WarnIfOperandImplicitlyConvertsNetField(context, node.Left); - if (!leftHasWarning) - this.WarnIfOperandImplicitlyConvertsNetField(context, node.Right); + BinaryExpressionSyntax binaryExpression = (BinaryExpressionSyntax)context.Node; + foreach (var pair in new[] { Tuple.Create(binaryExpression.Left, binaryExpression.Right), Tuple.Create(binaryExpression.Right, binaryExpression.Left) }) + { + // get node info + ExpressionSyntax curExpression = pair.Item1; // the side of the comparison being examined + ExpressionSyntax otherExpression = pair.Item2; // the other side + TypeInfo typeInfo = context.SemanticModel.GetTypeInfo(curExpression); + if (!this.IsNetType(typeInfo.Type)) + continue; + + // warn for implicit conversion + if (!this.IsNetType(typeInfo.ConvertedType)) + { + context.ReportDiagnostic(Diagnostic.Create(this.Rules["SMAPI001"], context.Node.GetLocation(), curExpression, typeInfo.Type.Name, typeInfo.ConvertedType)); + break; + } + + // warn for comparison to null + // An expression like `building.indoors != null` will sometimes convert `building.indoors` to NetFieldBase instead of object before comparison. Haven't reproduced this in unit tests yet. + Optional otherValue = context.SemanticModel.GetConstantValue(otherExpression); + if (otherValue.HasValue && otherValue.Value == null) + { + context.ReportDiagnostic(Diagnostic.Create(this.Rules["SMAPI001"], context.Node.GetLocation(), curExpression, typeInfo.Type.Name, "null")); + break; + } + } } catch (Exception ex) { @@ -241,22 +263,6 @@ namespace StardewModdingAPI.ModBuildConfig.Analyzer } } - /// Analyse one operand in a binary expression (like a and b in a == b) and add a diagnostic message if applicable. - /// The analysis context. - /// The operand expression. - /// Returns whether a diagnostic message was raised. - private bool WarnIfOperandImplicitlyConvertsNetField(SyntaxNodeAnalysisContext context, ExpressionSyntax operand) - { - TypeInfo operandType = context.SemanticModel.GetTypeInfo(operand); - if (this.IsNetType(operandType.Type) && !this.IsNetType(operandType.ConvertedType)) - { - context.ReportDiagnostic(Diagnostic.Create(this.Rules["SMAPI001"], context.Node.GetLocation(), operand, operandType.Type.Name, operandType.ConvertedType)); - return true; - } - - return false; - } - /// Get whether a type symbol references a Netcode type. /// The type symbol. private bool IsNetType(ITypeSymbol typeSymbol) -- cgit