private void LookForElementFactoryMethodParamsThatAreGivenAnArrayInsteadOfIndividualStaticElements(SyntaxNodeAnalysisContext context)
{
var invocation = context.Node as InvocationExpressionSyntax;
if (invocation == null)
return;
// The element factory methods are always of the form
// public extern static ReactElement A(AnchorAttributes properties, params Union<ReactElement, string>[] children);
// so the first do-no-more-work condition is if there are not precisely two arguments passed
var arguments = invocation.ArgumentList.Arguments;
if (arguments.Count != 2)
return;
// The next early exit is to leave now if the second argument isn't a named reference, invocation, member access, etc.. - actually, it's easier to look
// for values which CAN'T result in a dynamic array being returned, which basically means a literal value (such as null) or a cast from a literal. If we
// can break out now then we can avoid doing the more expensive work around determining the type of the second argument in case it's the array type that
// we're looking for).
var secondArgument = invocation.ArgumentList.Arguments[1].Expression;
if (IsLiteralOrCastFromLiteral(secondArgument))
return;
var method = context.SemanticModel.GetSymbolInfo(invocation).Symbol as IMethodSymbol;
if (method == null)
return; // If the method call is not valid then there's no way to confirm or deny that the call is acceptable (or even to determine whether it's a Bridge.React.DOM method)
// If the method isn't a Bridge.React.DOM element factory method then it's not something that we should be checking
if ((method.ContainingAssembly.Identity.Name != "Bridge.React") || (method.ContainingType.Name != "DOM"))
return;
// Try to confirm that the last argument of the method is "Union<ReactElement, string>[]" since that's the type that enable the warning to be bypassed
// most easily
if (!IsAnyOrUnionReactElementOrStringArray(method.Parameters.Last().Type))
return;
// Try to confirm that the value specified as the parameter value is "Union<ReactElement, string>[]" (since this argument will be a params array in the
// factory methods, it's possible that the value could be a single ReactElement or a single string - which would be fine)
// - context.SemanticModel.GetTypeInfo will never return null since it returns a struct value
// - We're interested in the ConvertedType of the value, for cases where the value itself is not an "Union<ReactElement, string>[]" but one which may
// be cast to that type, since that's what's important here
var argumentValueType = context.SemanticModel.GetTypeInfo(secondArgument).ConvertedType;
if ((argumentValueType == null) || (argumentValueType is IErrorTypeSymbol) || !IsAnyOrUnionReactElementOrStringArray(argumentValueType))
return;
context.ReportDiagnostic(Diagnostic.Create(
DynamicChildrenUniqueIdWarningBypassRule,
secondArgument.GetLocation(),
method.Name
));
}