private void LookForComponentClassWithNonEmptyConstructors(SyntaxNodeAnalysisContext context)
{
var constructor = context.Node as ConstructorDeclarationSyntax;
if (constructor == null)
return;
if ((constructor.Body == null) // If the code is in an invalid state then the Body property might be null - safe to ignore
|| !constructor.Body.ChildNodes().Any() // If the constructor is empty then that's what we want to make sure of - so exit now
|| constructor.Modifiers.Any(modifier => modifier.Kind() == SyntaxKind.StaticKeyword)) // Static constructors WILL be executed (by Bridge), it's only instance constructors that aren't called (by React)
return;
var classDeclaration = constructor.Ancestors().OfType<ClassDeclarationSyntax>().FirstOrDefault();
if (classDeclaration == null)
return;
// Note: It would seem more sensible to use typeof() to get the full type names to pass to IsDerivedFromClass but we can't do that because
// we can't add a reference from the project to the "NonBridgeBuild" project because then that reference would get pulled in to the project
// that the React Bindings and this Analyser were being added to - this would confuse the compiler because that project would have the "real"
// project reference (the Bridge build of Bridge.React) AND it would get the built-for-CLR project reference, which would confuse it no end.
var classDelarationSymbol = context.SemanticModel.GetDeclaredSymbol(classDeclaration);
string baseClassNameIfApplicable;
if (IsDerivedFromClass(classDelarationSymbol, "Bridge.React.Component`2"))
baseClassNameIfApplicable = "Component";
else if (IsDerivedFromClass(classDelarationSymbol, "Bridge.React.StatelessComponent`1"))
baseClassNameIfApplicable = "StatelessComponent";
else if (IsDerivedFromClass(classDelarationSymbol, "Bridge.React.PureComponent`1"))
baseClassNameIfApplicable = "PureComponent";
else
return;
context.ReportDiagnostic(Diagnostic.Create(
EmptyConstructorRule,
constructor.GetLocation(),
classDeclaration.Identifier.Text,
baseClassNameIfApplicable
));
}