private static void HandleTypeDeclaration(SyntaxNodeAnalysisContext context, StyleCopSettings settings) { var elementOrder = settings.OrderingRules.ElementOrder; int readonlyIndex = elementOrder.IndexOf(OrderingTrait.Readonly); if (readonlyIndex < 0) { return; } var typeDeclaration = (TypeDeclarationSyntax)context.Node; // This variable is null when the previous member is not a field. FieldDeclarationSyntax previousField = null; var previousFieldConst = true; var previousFieldStatic = false; var previousFieldReadonly = false; var previousAccessLevel = AccessLevel.NotSpecified; foreach (var member in typeDeclaration.Members) { if (!(member is FieldDeclarationSyntax field)) { previousField = null; continue; } var modifiers = member.GetModifiers(); var currentAccessLevel = MemberOrderHelper.GetAccessLevelForOrdering(member, modifiers); bool currentFieldConst = modifiers.Any(SyntaxKind.ConstKeyword); bool currentFieldStatic = currentFieldConst || modifiers.Any(SyntaxKind.StaticKeyword); bool currentFieldReadonly = currentFieldConst || modifiers.Any(SyntaxKind.ReadOnlyKeyword); if (previousField == null) { previousField = field; previousFieldConst = currentFieldConst; previousFieldStatic = currentFieldStatic; previousFieldReadonly = currentFieldReadonly; previousAccessLevel = currentAccessLevel; continue; } bool compareReadonly = true; for (int j = 0; compareReadonly && j < readonlyIndex; j++) { switch (elementOrder[j]) { case OrderingTrait.Kind: // This analyzer only ever looks at sequences of fields. continue; case OrderingTrait.Accessibility: if (previousAccessLevel != currentAccessLevel) { compareReadonly = false; } continue; case OrderingTrait.Constant: if (previousFieldConst != currentFieldConst) { compareReadonly = false; } continue; case OrderingTrait.Static: if (previousFieldStatic != currentFieldStatic) { compareReadonly = false; } continue; case OrderingTrait.Readonly: default: continue; } } if (compareReadonly) { if (currentFieldReadonly && !previousFieldReadonly) { context.ReportDiagnostic(Diagnostic.Create(Descriptor, NamedTypeHelpers.GetNameOrIdentifierLocation(member))); } } previousField = field; previousFieldConst = currentFieldConst; previousFieldStatic = currentFieldStatic; previousFieldReadonly = currentFieldReadonly; previousAccessLevel = currentAccessLevel; } }
private static void HandleMemberList(SyntaxNodeAnalysisContext context, ImmutableArray <OrderingTrait> elementOrder, int staticIndex, SyntaxList <MemberDeclarationSyntax> members) { var previousSyntaxKind = SyntaxKind.None; var previousAccessLevel = AccessLevel.NotSpecified; var previousMemberStatic = true; var previousMemberConstant = false; var previousMemberReadonly = false; foreach (var member in members) { var modifiers = member.GetModifiers(); var currentSyntaxKind = member.Kind(); currentSyntaxKind = currentSyntaxKind == SyntaxKind.EventFieldDeclaration ? SyntaxKind.EventDeclaration : currentSyntaxKind; var currentAccessLevel = MemberOrderHelper.GetAccessLevelForOrdering(member, modifiers); bool currentMemberConstant = modifiers.Any(SyntaxKind.ConstKeyword); bool currentMemberReadonly = currentMemberConstant || modifiers.Any(SyntaxKind.ReadOnlyKeyword); bool currentMemberStatic = currentMemberConstant || modifiers.Any(SyntaxKind.StaticKeyword); bool compareStatic = true; for (int j = 0; compareStatic && j < staticIndex; j++) { switch (elementOrder[j]) { case OrderingTrait.Accessibility: if (currentAccessLevel != previousAccessLevel) { compareStatic = false; } continue; case OrderingTrait.Readonly: if (currentMemberReadonly != previousMemberReadonly) { compareStatic = false; } continue; case OrderingTrait.Constant: if (currentMemberConstant != previousMemberConstant) { compareStatic = false; } continue; case OrderingTrait.Kind: if (previousSyntaxKind != currentSyntaxKind) { compareStatic = false; } continue; case OrderingTrait.Static: default: continue; } } if (compareStatic) { if (currentMemberStatic && !previousMemberStatic) { context.ReportDiagnostic( Diagnostic.Create( Descriptor, NamedTypeHelpers.GetNameOrIdentifierLocation(member), AccessLevelHelper.GetName(currentAccessLevel))); } } previousSyntaxKind = currentSyntaxKind; previousAccessLevel = currentAccessLevel; previousMemberStatic = currentMemberStatic; previousMemberConstant = currentMemberConstant; previousMemberReadonly = currentMemberReadonly; } }
private static void HandleTypeDeclaration(SyntaxNodeAnalysisContext context, StyleCopSettings settings) { var elementOrder = settings.OrderingRules.ElementOrder; int constantIndex = elementOrder.IndexOf(OrderingTrait.Constant); if (constantIndex < 0) { return; } var typeDeclaration = (TypeDeclarationSyntax)context.Node; var members = typeDeclaration.Members; var previousFieldConstant = true; var previousFieldStatic = false; var previousFieldReadonly = false; var previousAccessLevel = AccessLevel.NotSpecified; foreach (var member in members) { var field = member as FieldDeclarationSyntax; if (field == null) { continue; } AccessLevel currentAccessLevel = MemberOrderHelper.GetAccessLevelForOrdering(field, field.Modifiers); bool currentFieldConstant = field.Modifiers.Any(SyntaxKind.ConstKeyword); bool currentFieldReadonly = currentFieldConstant || field.Modifiers.Any(SyntaxKind.ReadOnlyKeyword); bool currentFieldStatic = currentFieldConstant || field.Modifiers.Any(SyntaxKind.StaticKeyword); bool compareConst = true; for (int j = 0; compareConst && j < constantIndex; j++) { switch (elementOrder[j]) { case OrderingTrait.Accessibility: if (currentAccessLevel != previousAccessLevel) { compareConst = false; } continue; case OrderingTrait.Readonly: if (currentFieldReadonly != previousFieldReadonly) { compareConst = false; } continue; case OrderingTrait.Static: if (currentFieldStatic != previousFieldStatic) { compareConst = false; } continue; case OrderingTrait.Kind: // Only fields may be marked const, and all fields have the same kind. continue; case OrderingTrait.Constant: default: continue; } } if (compareConst) { if (!previousFieldConstant && currentFieldConstant) { context.ReportDiagnostic(Diagnostic.Create(Descriptor, NamedTypeHelpers.GetNameOrIdentifierLocation(member))); } } previousFieldConstant = currentFieldConstant; previousFieldReadonly = currentFieldReadonly; previousFieldStatic = currentFieldStatic; previousAccessLevel = currentAccessLevel; } }
private static void HandleMemberList(SyntaxNodeAnalysisContext context, ImmutableArray <OrderingTrait> elementOrder, int accessibilityIndex, SyntaxList <MemberDeclarationSyntax> members, AccessLevel defaultAccessLevel) { MemberDeclarationSyntax previousMember = null; var previousSyntaxKind = SyntaxKind.None; var previousAccessLevel = AccessLevel.NotSpecified; bool previousIsConst = false; bool previousIsReadonly = false; bool previousIsStatic = false; foreach (var member in members) { var currentSyntaxKind = member.Kind(); currentSyntaxKind = currentSyntaxKind == SyntaxKind.EventFieldDeclaration ? SyntaxKind.EventDeclaration : currentSyntaxKind; // if the SyntaxKind of this member (e.g. SyntaxKind.IncompleteMember) will not // be handled, skip early. if (!MemberKinds.Contains(currentSyntaxKind)) { continue; } var modifiers = member.GetModifiers(); AccessLevel currentAccessLevel = MemberOrderHelper.GetAccessLevelForOrdering(member, modifiers); bool currentIsConst = modifiers.Any(SyntaxKind.ConstKeyword); bool currentIsReadonly = modifiers.Any(SyntaxKind.ReadOnlyKeyword); bool currentIsStatic = modifiers.Any(SyntaxKind.StaticKeyword); if (previousAccessLevel != AccessLevel.NotSpecified) { bool compareAccessLevel = true; for (int j = 0; compareAccessLevel && j < accessibilityIndex; j++) { switch (elementOrder[j]) { case OrderingTrait.Kind: if (previousSyntaxKind != currentSyntaxKind) { compareAccessLevel = false; } continue; case OrderingTrait.Constant: if (previousIsConst != currentIsConst) { compareAccessLevel = false; } continue; case OrderingTrait.Readonly: if (previousIsReadonly != currentIsReadonly) { compareAccessLevel = false; } continue; case OrderingTrait.Static: if (previousIsStatic != currentIsStatic) { compareAccessLevel = false; } continue; case OrderingTrait.Accessibility: default: continue; } } if (compareAccessLevel && currentAccessLevel > previousAccessLevel) { context.ReportDiagnostic( Diagnostic.Create( Descriptor, NamedTypeHelpers.GetNameOrIdentifierLocation(member), AccessLevelHelper.GetName(currentAccessLevel), AccessLevelHelper.GetName(previousAccessLevel))); } } previousMember = member; previousSyntaxKind = currentSyntaxKind; previousAccessLevel = currentAccessLevel; previousIsConst = currentIsConst; previousIsReadonly = currentIsReadonly; previousIsStatic = currentIsStatic; } }
private static void HandleMemberList(SyntaxNodeAnalysisContext context, ImmutableArray <OrderingTrait> elementOrder, int kindIndex, SyntaxList <MemberDeclarationSyntax> members, ImmutableArray <SyntaxKind> order) { for (int i = 0; i < members.Count - 1; i++) { if (members[i + 1].IsKind(SyntaxKind.IncompleteMember)) { i++; continue; } if (members[i].IsKind(SyntaxKind.IncompleteMember)) { continue; } bool compareKind = true; for (int j = 0; compareKind && j < kindIndex; j++) { switch (elementOrder[j]) { case OrderingTrait.Accessibility: if (MemberOrderHelper.GetAccessLevelForOrdering(members[i + 1], members[i + 1].GetModifiers()) != MemberOrderHelper.GetAccessLevelForOrdering(members[i], members[i].GetModifiers())) { compareKind = false; } continue; case OrderingTrait.Constant: case OrderingTrait.Readonly: // Only fields may be marked const or readonly, and all fields have the same kind. continue; case OrderingTrait.Static: bool currentIsStatic = members[i].GetModifiers().Any(SyntaxKind.StaticKeyword); bool nextIsStatic = members[i + 1].GetModifiers().Any(SyntaxKind.StaticKeyword); if (currentIsStatic != nextIsStatic) { compareKind = false; } continue; case OrderingTrait.Kind: default: continue; } } if (!compareKind) { continue; } var elementSyntaxKind = members[i].Kind(); elementSyntaxKind = elementSyntaxKind == SyntaxKind.EventFieldDeclaration ? SyntaxKind.EventDeclaration : elementSyntaxKind; int index = order.IndexOf(elementSyntaxKind); var nextElementSyntaxKind = members[i + 1].Kind(); nextElementSyntaxKind = nextElementSyntaxKind == SyntaxKind.EventFieldDeclaration ? SyntaxKind.EventDeclaration : nextElementSyntaxKind; int nextIndex = order.IndexOf(nextElementSyntaxKind); if (index > nextIndex) { context.ReportDiagnostic(Diagnostic.Create(Descriptor, NamedTypeHelpers.GetNameOrIdentifierLocation(members[i + 1]), MemberNames[nextElementSyntaxKind], MemberNames[elementSyntaxKind])); } } }