private void AnalyzeMethodInvocationInDacProperty(DacPropertyInfo property, HashSet <INamedTypeSymbol> whiteList, SymbolAnalysisContext context, PXContext pxContext, SemanticModel semanticModel) { foreach (SyntaxNode node in property.Node.DescendantNodes()) { context.CancellationToken.ThrowIfCancellationRequested(); if (node is InvocationExpressionSyntax invocation) { ISymbol symbol = semanticModel.GetSymbolInfo(invocation, context.CancellationToken).Symbol; if (symbol == null || !(symbol is IMethodSymbol method) || method.IsStatic || method.IsExtensionMethod) { continue; } bool inWhitelist = whiteList.Contains(method.ContainingType) || whiteList.Contains(method.ContainingType.ConstructedFrom); if (inWhitelist) { continue; } context.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(Descriptors.PX1032_DacPropertyCannotContainMethodInvocations, invocation.GetLocation()), pxContext.CodeAnalysisSettings); } else if (node is ObjectCreationExpressionSyntax) { context.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(Descriptors.PX1032_DacPropertyCannotContainMethodInvocations, node.GetLocation()), pxContext.CodeAnalysisSettings); } } }
public override void Analyze(SymbolAnalysisContext context, PXContext pxContext, PXGraphSemanticModel graph) { ITypeSymbol declaredPrimaryDacType = graph.Symbol.GetDeclaredPrimaryDacFromGraphOrGraphExtension(pxContext); if (declaredPrimaryDacType == null || context.CancellationToken.IsCancellationRequested) { return; } bool hasViewForPrimaryDac = graph.Views.Select(view => view.DAC).Contains(declaredPrimaryDacType); if (hasViewForPrimaryDac || context.CancellationToken.IsCancellationRequested) { return; } Location location = GetLocation(graph, declaredPrimaryDacType, context); if (location == null) { return; } context.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(Descriptors.PX1018_NoPrimaryViewForPrimaryDac, location), pxContext.CodeAnalysisSettings); }
public override void Analyze(SymbolAnalysisContext context, PXContext pxContext, DacSemanticModel dac) { context.CancellationToken.ThrowIfCancellationRequested(); var dacAttributes = dac.Symbol.GetAttributes(); var pxCacheNameAttribute = pxContext.AttributeTypes.PXCacheNameAttribute; var pxHiddenAttribute = pxContext.AttributeTypes.PXHiddenAttribute; bool hasPXCacheNameAttribute = false; bool hasPXHiddenAttribute = false; foreach (var attribute in dacAttributes.Where(a => a.AttributeClass != null)) { if (attribute.AttributeClass.InheritsFromOrEquals(pxCacheNameAttribute)) { hasPXCacheNameAttribute = true; } if (attribute.AttributeClass.InheritsFromOrEquals(pxHiddenAttribute)) { hasPXHiddenAttribute = true; } if (hasPXCacheNameAttribute || hasPXHiddenAttribute) { return; } } var diagnostic = Diagnostic.Create(Descriptors.PX1094_DacShouldHaveUiAttribute, dac.Node.Identifier.GetLocation()); context.ReportDiagnosticWithSuppressionCheck(diagnostic, pxContext.CodeAnalysisSettings); }
private void CheckIfStringLengthIsSufficientForAutoNumbering(SymbolAnalysisContext context, AttributeInformation attributeInformation, DacPropertyInfo dacProperty) { var dbBoundStringAttribute = attributeInformation.Context.FieldAttributes.PXDBStringAttribute; var unboundStringAttribute = attributeInformation.Context.FieldAttributes.PXStringAttribute; var stringAttributes = dacProperty.Attributes .Where(a => IsStringAttribute(a, attributeInformation, dbBoundStringAttribute, unboundStringAttribute)) .ToList(); if (stringAttributes.Count != 1) { return; } AttributeInfo stringAttribute = stringAttributes[0]; int? stringLength = GetStringLengthFromStringAttribute(stringAttribute); int minAllowedLength = attributeInformation.Context.AttributeTypes.AutoNumberAttribute.MinAutoNumberLength; if (stringLength.HasValue && stringLength < minAllowedLength) { var attributeLocation = GetLocationToReportInsufficientStringLength(context, stringAttribute, stringLength.Value); var diagnostic = Diagnostic.Create(Descriptors.PX1020_InsufficientStringLengthForDacPropertyWithAutoNumbering, attributeLocation, minAllowedLength); context.ReportDiagnosticWithSuppressionCheck(diagnostic, attributeInformation.Context.CodeAnalysisSettings); } }
private static void AnalyzeUnboundProperty(SymbolAnalysisContext symbolContext, PXContext pxContext, DacSemanticModel dacOrExtension, DacPropertyInfo property) { var(pxDefaultAttribute, hasPersistingCheckNothing) = GetPXDefaultInfo(pxContext, property); if (pxDefaultAttribute == null || hasPersistingCheckNothing) { return; } var attributeLocation = GetAttributeLocation(pxDefaultAttribute, symbolContext.CancellationToken); if (attributeLocation == null) { return; } var diagnosticProperties = ImmutableDictionary <string, string> .Empty .Add(DiagnosticProperty.IsBoundField, bool.FalseString); var descriptor = dacOrExtension.DacType == DacType.Dac ? Descriptors.PX1030_DefaultAttibuteToExistingRecordsOnDAC : Descriptors.PX1030_DefaultAttibuteToExistingRecordsError; var diagnostic = Diagnostic.Create(descriptor, attributeLocation, diagnosticProperties); symbolContext.ReportDiagnosticWithSuppressionCheck(diagnostic, pxContext.CodeAnalysisSettings); }
public override void Analyze(SymbolAnalysisContext context, PXContext pxContext, DacSemanticModel dac) { foreach (DacFieldInfo dacField in dac.DeclaredFields) { context.CancellationToken.ThrowIfCancellationRequested(); if (dacField.Symbol.BaseType.SpecialType != SpecialType.System_Object || AlreadyStronglyTyped(dacField.Symbol, pxContext)) { continue; } Location location = dacField.Symbol.Locations.FirstOrDefault(); if (location != null && dac.PropertiesByNames.TryGetValue(dacField.Name, out DacPropertyInfo property)) { string propertyTypeName = GetPropertyTypeName(property.Symbol, pxContext); if (propertyTypeName == null || !PropertyTypeToFieldType.ContainsKey(propertyTypeName)) { continue; } var args = ImmutableDictionary.CreateBuilder <string, string>(); args.Add(CorrespondingPropertyType, propertyTypeName); context.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(Descriptors.PX1060_LegacyBqlField, location, args.ToImmutable(), dacField.Name), pxContext.CodeAnalysisSettings); } } }
private static void AnalyzeProperty(DacPropertyInfo property, SymbolAnalysisContext context, PXContext pxContext, IEnumerable <INamedTypeSymbol> typeAttributesSet) { var attributeTypes = property.Symbol.GetAttributes() .Select(a => a.AttributeClass) .ToList(capacity: 4); bool hasListAttribute = attributeTypes.Any(type => type.ImplementsInterface(pxContext.IPXLocalizableList)); if (!hasListAttribute) { return; } //TODO we need to use FieldTypeAttributesRegister to perform complete analysis with consideration for aggregate attributes bool hasTypeAttribute = attributeTypes.Any(propertyAttributeType => typeAttributesSet.Any(typeAttribute => propertyAttributeType.InheritsFromOrEquals(typeAttribute))); if (!hasTypeAttribute) { context.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(Descriptors.PX1002_MissingTypeListAttributeAnalyzer, property.Symbol.Locations.FirstOrDefault()), pxContext.CodeAnalysisSettings); } }
protected virtual void ReportKeyDeclarationWithWrongName(SymbolAnalysisContext symbolContext, PXContext context, DacSemanticModel dac, INamedTypeSymbol keyDeclaration, RefIntegrityDacKeyType dacKeyType) { var keyDeclarationNode = keyDeclaration.GetSyntax(symbolContext.CancellationToken); Location location = (keyDeclarationNode as ClassDeclarationSyntax)?.Identifier.GetLocation() ?? keyDeclarationNode?.GetLocation(); Location dacLocation = dac.Node.GetLocation(); DiagnosticDescriptor px1036Descriptor = GetWrongKeyNameDiagnosticDescriptor(dacKeyType); if (location == null || dacLocation == null || px1036Descriptor == null) { return; } var additionalLocations = new[] { dacLocation }; var diagnosticProperties = new Dictionary <string, string> { { nameof(RefIntegrityDacKeyType), dacKeyType.ToString() } }; if (dacKeyType == RefIntegrityDacKeyType.UniqueKey) { diagnosticProperties.Add(nameof(UniqueKeyCodeFixType), UniqueKeyCodeFixType.SingleUniqueKey.ToString()); } symbolContext.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(px1036Descriptor, location, additionalLocations, diagnosticProperties.ToImmutableDictionary()), context.CodeAnalysisSettings); }
private void AnalyzeMethodDeclarationInDac(MethodDeclarationSyntax method, SymbolAnalysisContext context, PXContext pxContext) { if (!method.IsStatic()) { context.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(Descriptors.PX1031_DacCannotContainInstanceMethods, method.Identifier.GetLocation()), pxContext.CodeAnalysisSettings); } }
public override void Analyze(SymbolAnalysisContext context, PXContext pxContext, DacSemanticModel dac) { if (dac.Symbol.BaseType.Name == TypeNames.PXCacheExtension) { if (!dac.Symbol.IsSealed) { context.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(Descriptors.PX1011_InheritanceFromPXCacheExtension, dac.Symbol.Locations.First()), pxContext.CodeAnalysisSettings); } } else { context.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(Descriptors.PX1009_InheritanceFromPXCacheExtension, dac.Symbol.Locations.First()), pxContext.CodeAnalysisSettings); } }
private void CheckBigGroupOfKeysForPrimaryKeyAndUniqueKeysContainer(SymbolAnalysisContext symbolContext, PXContext context, DacSemanticModel dac, List <INamedTypeSymbol> keyDeclarations, Dictionary <INamedTypeSymbol, List <ITypeSymbol> > dacFieldsByKey) { var primaryKey = keyDeclarations.Find(key => key.Name == ReferentialIntegrity.PrimaryKeyClassName); if (primaryKey == null) { //If there is no primary key - try to find suitable unique key and rename it. Otherwise report no primary key in DAC ProcessDacWithoutPrimaryKeyAndWithSeveralUniqueKeys(symbolContext, context, dac, keyDeclarations, dacFieldsByKey); return; } INamedTypeSymbol uniqueKeysContainer = dac.Symbol.GetTypeMembers(ReferentialIntegrity.UniqueKeyClassName) .FirstOrDefault(); //We can register code fix only if there is no UK nested type in DAC or there is a public static UK class. Otherwise we will break the code. bool registerCodeFix = uniqueKeysContainer == null || (uniqueKeysContainer.DeclaredAccessibility == Accessibility.Public && uniqueKeysContainer.IsStatic); List <INamedTypeSymbol> keysNotInContainer = GetKeysNotInContainer(keyDeclarations, uniqueKeysContainer, primaryKey); if (keysNotInContainer.Count == 0) { return; } symbolContext.CancellationToken.ThrowIfCancellationRequested(); Location dacLocation = dac.Node.GetLocation(); var keysNotInContainerLocations = GetKeysLocations(keysNotInContainer, symbolContext.CancellationToken).ToList(capacity: keysNotInContainer.Count); if (dacLocation == null || keysNotInContainerLocations.Count == 0) { return; } var dacLocationArray = new[] { dacLocation }; var diagnosticProperties = new Dictionary <string, string> { { nameof(RefIntegrityDacKeyType), RefIntegrityDacKeyType.UniqueKey.ToString() }, { nameof(UniqueKeyCodeFixType), UniqueKeyCodeFixType.MultipleUniqueKeys.ToString() }, { DiagnosticProperty.RegisterCodeFix, registerCodeFix.ToString() } } .ToImmutableDictionary(); foreach (Location keyLocation in keysNotInContainerLocations) { var otherKeyLocations = keysNotInContainerLocations.Where(location => location != keyLocation); var additionalLocations = dacLocationArray.Concat(otherKeyLocations); symbolContext.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(Descriptors.PX1036_WrongDacMultipleUniqueKeyDeclarations, keyLocation, additionalLocations, diagnosticProperties), context.CodeAnalysisSettings); } }
public override void VisitInvocationExpression(InvocationExpressionSyntax node) { _context.CancellationToken.ThrowIfCancellationRequested(); var methodSymbol = _semanticModel.GetSymbolInfo(node).Symbol as IMethodSymbol; if (methodSymbol != null && IsMethodForbidden(methodSymbol)) { bool found = node.ArgumentList.Arguments .Where(arg => arg.Expression != null) .Select(arg => _semanticModel.GetSymbolInfo(arg.Expression).Symbol as ILocalSymbol) .Any(variable => variable != null && _rowVariables.Contains(variable)); if (!found) { var walker = new EventArgsRowWalker(_semanticModel, _pxContext); node.ArgumentList.Accept(walker); found = walker.Success; } if (found && _analysisMode == RowChangesAnalysisMode.ChangesForbiddenForRowFromEventArgs) { _context.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create( _pxContext.CodeAnalysisSettings.IsvSpecificAnalyzersEnabled ? Descriptors.PX1047_RowChangesInEventHandlersForbiddenForArgs : Descriptors.PX1047_RowChangesInEventHandlersForbiddenForArgs_NonISV, node.GetLocation(), _messageArgs), _pxContext.CodeAnalysisSettings); } else if (!found && _analysisMode == RowChangesAnalysisMode.ChangesAllowedOnlyForRowFromEventArgs) { _context.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create( Descriptors.PX1048_RowChangesInEventHandlersAllowedForArgsOnly, node.GetLocation(), _messageArgs), _pxContext.CodeAnalysisSettings); } } }
private void ReportNoPrimaryKeyDeclarationsInDac(SymbolAnalysisContext symbolContext, PXContext context, DacSemanticModel dac) { Location location = dac.Node.Identifier.GetLocation() ?? dac.Node.GetLocation(); if (location != null) { symbolContext.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(Descriptors.PX1033_MissingDacPrimaryKeyDeclaration, location), context.CodeAnalysisSettings); } }
private void RegisterDiagnosticForIdentifier(SyntaxToken identifier, PXContext pxContext, SymbolAnalysisContext context) { bool isDeletedDatabaseRecord = string.Equals(identifier.ValueText, DeletedDatabaseRecord, StringComparison.OrdinalIgnoreCase); DiagnosticDescriptor descriptorToShow = isDeletedDatabaseRecord && !pxContext.CodeAnalysisSettings.IsvSpecificAnalyzersEnabled ? Descriptors.PX1027_ForbiddenFieldsInDacDeclaration_NonISV : Descriptors.PX1027_ForbiddenFieldsInDacDeclaration; context.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(descriptorToShow, identifier.GetLocation(), identifier.ValueText), pxContext.CodeAnalysisSettings); }
private void ReportDacPropertyTypeIsNotString(SymbolAnalysisContext context, PXContext pxContext, DacPropertyInfo dacProperty) { var autoNumberingAttribute = dacProperty.Attributes.FirstOrDefault(a => a.IsAutoNumberAttribute); var propertyTypeLocation = dacProperty.Node.Type.GetLocation(); if (propertyTypeLocation != null) { var diagnostic = Diagnostic.Create(Descriptors.PX1019_AutoNumberOnDacPropertyWithNonStringType, propertyTypeLocation); context.ReportDiagnosticWithSuppressionCheck(diagnostic, pxContext.CodeAnalysisSettings); } var attributeLocation = autoNumberingAttribute?.AttributeData.GetLocation(context.CancellationToken); if (attributeLocation != null) { var diagnostic = Diagnostic.Create(Descriptors.PX1019_AutoNumberOnDacPropertyWithNonStringType, attributeLocation); context.ReportDiagnosticWithSuppressionCheck(diagnostic, pxContext.CodeAnalysisSettings); } }
public override void Analyze(SymbolAnalysisContext context, PXContext pxContext, PXGraphSemanticModel pxGraph) { context.CancellationToken.ThrowIfCancellationRequested(); var constructorLocations = pxGraph.Symbol.InstanceConstructors.Where(constructor => !constructor.IsImplicitlyDeclared) .SelectMany(constructor => constructor.Locations); foreach (Location location in constructorLocations) { context.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(Descriptors.PX1040_ConstructorInGraphExtension, location), pxContext.CodeAnalysisSettings); } }
private static void AnalyzeDacField(DacFieldInfo dacFieldInfo, SymbolAnalysisContext symbolContext, PXContext pxContext) { symbolContext.CancellationToken.ThrowIfCancellationRequested(); if (dacFieldInfo.Symbol.IsAbstract) { return; } symbolContext.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(Descriptors.PX1024_DacNonAbstractFieldType, dacFieldInfo.Node.Identifier.GetLocation()), pxContext.CodeAnalysisSettings); }
private static void AnalyzeDelegate(SymbolAnalysisContext syntaxContext, PXContext pxContext) { IMethodSymbol method = syntaxContext.Symbol as IMethodSymbol; if (!IsDiagnosticValid(method, syntaxContext, pxContext)) { return; } var declaration = method.DeclaringSyntaxReferences[0]; var methodDeclaration = declaration.GetSyntax(syntaxContext.CancellationToken) as MethodDeclarationSyntax; if (methodDeclaration?.Body == null || syntaxContext.CancellationToken.IsCancellationRequested) { return; } SemanticModel semanticModel = syntaxContext.Compilation.GetSemanticModel(declaration.SyntaxTree); ILocalSymbol refStartRow = GetReferenceToStartRow(methodDeclaration, semanticModel, pxContext, syntaxContext.CancellationToken); if (refStartRow == null || syntaxContext.CancellationToken.IsCancellationRequested) { return; } var(selectSymbol, selectInvocation) = GetSelectSymbolAndInvocationNode(methodDeclaration, refStartRow, pxContext, semanticModel, syntaxContext.CancellationToken); if (selectSymbol == null || selectInvocation == null || syntaxContext.CancellationToken.IsCancellationRequested) { return; } AssignmentExpressionSyntax lastAssigment = GetLastStartRowResetAssignment(methodDeclaration); if (lastAssigment != null && lastAssigment.SpanStart > selectInvocation.Span.End) { return; } bool registerCodeFix = RegisterCodeFix(methodDeclaration, selectInvocation); var diagnosticProperties = new Dictionary <string, string> { { DiagnosticProperty.RegisterCodeFix, registerCodeFix.ToString() } }.ToImmutableDictionary(); syntaxContext.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create( Descriptors.PX1010_StartRowResetForPaging, selectInvocation.GetLocation(), diagnosticProperties), pxContext.CodeAnalysisSettings); }
public override void Analyze(SymbolAnalysisContext context, PXContext pxContext, DacSemanticModel dacOrDacExtenstion) { context.CancellationToken.ThrowIfCancellationRequested(); var dacConstructors = dacOrDacExtenstion.GetMemberNodes <ConstructorDeclarationSyntax>(); foreach (var constructor in dacConstructors) { context.CancellationToken.ThrowIfCancellationRequested(); context.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(Descriptors.PX1028_ConstructorInDacDeclaration, constructor.Identifier.GetLocation()), pxContext.CodeAnalysisSettings); } }
private bool ReportKeyWithUnboundDacField(SymbolAnalysisContext symbolContext, PXContext context, INamedTypeSymbol key, ClassDeclarationSyntax keyNode, ITypeSymbol unboundDacFieldInKey) { var location = GetUnboundDacFieldLocation(keyNode, unboundDacFieldInKey) ?? keyNode.Identifier.GetLocation() ?? keyNode.GetLocation(); if (location == null) { return(false); } symbolContext.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(Descriptors.PX1037_UnboundDacFieldInKeyDeclaration, location), context.CodeAnalysisSettings); return(true); }
private static void RegisterDiagnosticForAction(ISymbol actionSymbol, string primaryDacName, ImmutableDictionary <string, string> diagnosticProperties, SymbolAnalysisContext symbolContext, PXContext pxContext) { SyntaxNode symbolSyntax = actionSymbol.GetSyntax(symbolContext.CancellationToken); Location location = GetLocation(symbolSyntax); if (location == null) { return; } symbolContext.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(Descriptors.PX1012_PXActionOnNonPrimaryView, location, diagnosticProperties, actionSymbol.Name, primaryDacName), pxContext.CodeAnalysisSettings); }
private static void ReportDiagnostic(DiagnosticDescriptor descriptor, SymbolAnalysisContext symbolContext, PXContext pxContext, IEnumerable <DataViewInfo> viewsToShowDiagnostic, ITypeSymbol dac, ITypeSymbol baseDac) { foreach (DataViewInfo view in viewsToShowDiagnostic) { Location viewLocation = view.Symbol.Locations.FirstOrDefault(); if (viewLocation == null) { continue; } symbolContext.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(descriptor, viewLocation, dac.Name, baseDac.Name), pxContext.CodeAnalysisSettings); } }
public void Analyze(SymbolAnalysisContext symbolContext, PXContext pxContext, DacSemanticModel dacExtension) { symbolContext.CancellationToken.ThrowIfCancellationRequested(); // ShouldAnalyze already filtered everything and left only DAC extensions without IsActive // We just need to report them Location location = dacExtension.Node.Identifier.GetLocation(); if (location == null) { return; } symbolContext.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(Descriptors.PX1016_NoIsActiveMethodForDacExtension, location), pxContext.CodeAnalysisSettings); }
public override void VisitIdentifierName(IdentifierNameSyntax node) { ThrowIfCancellationRequested(); TypeInfo typeInfo = _semanticModel.GetTypeInfo(node, _context.CancellationToken); if (typeInfo.Type == null || !typeInfo.Type.IsPXGraphOrExtension(_pxContext)) { return; } _context.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(Descriptors.PX1029_PXGraphUsageInDac, node.GetLocation()), _pxContext.CodeAnalysisSettings); base.VisitIdentifierName(node); }
private void AnalyzeNamedType(SymbolAnalysisContext context, PXContext pxContext) { context.CancellationToken.ThrowIfCancellationRequested(); var typeSymbol = (INamedTypeSymbol)context.Symbol; if (typeSymbol != null && typeSymbol.InheritsFrom(pxContext.PXGraphExtensionType) && !typeSymbol.IsGraphExtensionBaseType()) { foreach (var constructor in typeSymbol.InstanceConstructors .Where(c => !c.IsImplicitlyDeclared)) { context.ReportDiagnosticWithSuppressionCheck(Diagnostic.Create( Descriptors.PX1040_ConstructorInGraphExtension, constructor.Locations.First()), pxContext.CodeAnalysisSettings); } } }
private bool CheckThatAllKeysHaveUniqueSetsOfFields(SymbolAnalysisContext symbolContext, PXContext context, List <INamedTypeSymbol> keyDeclarations, Dictionary <INamedTypeSymbol, List <ITypeSymbol> > dacFieldsByKey) { if (keyDeclarations.Count < 2 || dacFieldsByKey.Count == 0) { return(true); } // First obtain groups of keys which use same DAC fields. var keysGroupedByFields = GetKeysGroupedBySetOfFields(keyDeclarations, dacFieldsByKey, symbolContext.CancellationToken); // Get the groups of more than one key which use the same DAC fields set. Split these groups by their target DAC. // We don't do this for all keys at the previous step as a optimization for the most frequent case. // To split the key groups by their target DACs we need to extract the target DAC from them. Most of the keys use a unique set of DAC fields anyway, // so we don't need to make this redundant extraction for them. var duplicateKeySets = keysGroupedByFields.Values.Where(keys => keys.Count > 1) .SelectMany(keys => GetDuplicateKeysGroupsForSameTargetDAC(context, keys)); bool allFieldsUnique = true; // We group keys by sets of used fields and then report each set with duplicate keys separately, // passing the locations of other duplicate fields in a set to code fix. // This way if there are two different sets of duplicate keys the code fix will affect only the set to which it was applied foreach (List <INamedTypeSymbol> duplicateKeys in duplicateKeySets) { allFieldsUnique = false; var locations = duplicateKeys.Select(declaration => declaration.GetSyntax(symbolContext.CancellationToken)) .OfType <ClassDeclarationSyntax>() .Select(keyClassDeclaration => keyClassDeclaration.Identifier.GetLocation() ?? keyClassDeclaration.GetLocation()) .Where(location => location != null) .ToList(capacity: duplicateKeys.Count); for (int i = 0; i < locations.Count; i++) { Location location = locations[i]; var otherLocations = locations.Where((_, index) => index != i); symbolContext.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(Descriptors.PX1035_MultipleKeyDeclarationsInDacWithSameFields, location, otherLocations), context.CodeAnalysisSettings); } } return(allFieldsUnique); }
public override void VisitObjectCreationExpression(ObjectCreationExpressionSyntax node) { if (node.Type == null || !(_semanticModel.GetSymbolInfo(node.Type).Symbol is ITypeSymbol typeSymbol)) { base.VisitObjectCreationExpression(node); return; } DiagnosticDescriptor descriptor = GetDiagnosticDescriptor(typeSymbol); if (descriptor != null) { _context.ReportDiagnosticWithSuppressionCheck(Diagnostic.Create(descriptor, node.GetLocation()), _pxContext.CodeAnalysisSettings); } base.VisitObjectCreationExpression(node); }
public void Analyze(SymbolAnalysisContext symbolContext, PXContext pxContext, PXGraphSemanticModel graphExtension) { symbolContext.CancellationToken.ThrowIfCancellationRequested(); // ShouldAnalyze already filtered everything and left only graph extensions without IsActive // We just need to report them var syntaxNode = graphExtension.Symbol.GetSyntax(symbolContext.CancellationToken); Location location = (syntaxNode as ClassDeclarationSyntax)?.Identifier.GetLocation() ?? syntaxNode?.GetLocation(); if (location == null) { return; } symbolContext.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(Descriptors.PX1016_NoIsActiveMethodForGraphExtension, location), pxContext.CodeAnalysisSettings); }
private static void CheckIdentifierForUnderscores(SyntaxToken identifier, SymbolAnalysisContext context, PXContext pxContext) { if (!identifier.ValueText.Contains("_")) { return; } bool registerCodeFix = !IdentifierContainsOnlyUnderscores(identifier.ValueText); var diagnosticProperties = new Dictionary <string, string> { { DiagnosticProperty.RegisterCodeFix, registerCodeFix.ToString() } }.ToImmutableDictionary(); context.ReportDiagnosticWithSuppressionCheck( Diagnostic.Create(Descriptors.PX1026_UnderscoresInDacDeclaration, identifier.GetLocation(), diagnosticProperties), pxContext.CodeAnalysisSettings); }
private void CheckActionHandlerReturnType(SymbolAnalysisContext context, PXContext pxContext, MethodDeclarationSyntax node, IMethodSymbol symbol) { context.CancellationToken.ThrowIfCancellationRequested(); if (pxContext.SystemTypes.IEnumerable.Equals(symbol.ReturnType)) { return; } if (!StartsLongOperation(pxContext, context.Compilation, node, context.CancellationToken)) { return; } var diagnostic = Diagnostic.Create( Descriptors.PX1013_PXActionHandlerInvalidReturnType, node.Identifier.GetLocation()); context.ReportDiagnosticWithSuppressionCheck(diagnostic, pxContext.CodeAnalysisSettings); }