protected override void AnalyzeSymbol(SymbolAnalysisContext context, PXContext pxContext) { context.CancellationToken.ThrowIfCancellationRequested(); if (!(context.Symbol is INamedTypeSymbol type)) { return; } var inferredDacModel = DacSemanticModel.InferModel(pxContext, type, context.CancellationToken); if (inferredDacModel == null) { return; } ParallelOptions parallelOptions = new ParallelOptions { CancellationToken = context.CancellationToken }; Parallel.ForEach(_innerAnalyzers, parallelOptions, innerAnalyzer => { context.CancellationToken.ThrowIfCancellationRequested(); if (innerAnalyzer.ShouldAnalyze(pxContext, inferredDacModel)) { innerAnalyzer.Analyze(context, pxContext, inferredDacModel); } }); }
protected virtual bool TryToInferDacOrDacExtensionSemanticModel(INamedTypeSymbol dacSymbol, PXContext context, out ISemanticModel dacSemanticModel, CancellationToken cancellationToken = default) { dacSemanticModel = DacSemanticModel.InferModel(context, dacSymbol, cancellationToken); return(dacSemanticModel != null); }
private Task <Document> AddPrimaryKeyDeclarationToDacAsync(Document document, SyntaxNode root, ClassDeclarationSyntax dacNode, PXContext pxContext, INamedTypeSymbol dacTypeSymbol, CancellationToken cancellation) { cancellation.ThrowIfCancellationRequested(); var dacSemanticModel = DacSemanticModel.InferModel(pxContext, dacTypeSymbol, cancellation); List <DacPropertyInfo> dacKeys = dacSemanticModel?.DacProperties .Where(property => property.IsKey) .OrderBy(property => property.DeclarationOrder) .ToList(capacity: 4); if (dacKeys.IsNullOrEmpty() || dacKeys.Count > PXReferentialIntegritySymbols.MaxPrimaryKeySize) { return(Task.FromResult(document)); } var primaryKeyNode = CreatePrimaryKeyNode(document, pxContext, dacSemanticModel, dacKeys); var newDacNode = dacNode.WithMembers( dacNode.Members.Insert(0, primaryKeyNode)); var changedRoot = root.ReplaceNode(dacNode, newDacNode); changedRoot = AddUsingsForReferentialIntegrityNamespace(changedRoot); var modifiedDocument = document.WithSyntaxRoot(changedRoot); return(Task.FromResult(modifiedDocument)); }
private List <DacPropertyInfo> GetDacPropertiesWithForeignKeys(PXContext pxContext, INamedTypeSymbol dacTypeSymbol, CancellationToken cancellation) { var foreignKeyAttributes = GetForeignKeyAttributes(pxContext); if (foreignKeyAttributes.Count == 0) { return(new List <DacPropertyInfo>()); } var dacSemanticModel = DacSemanticModel.InferModel(pxContext, dacTypeSymbol, cancellation); if (dacSemanticModel == null || dacSemanticModel.DacType != DacType.Dac) { return(new List <DacPropertyInfo>()); } var selectorAttribute = pxContext.AttributeTypes.PXSelectorAttribute.Type; var dimensionSelectorAttribute = pxContext.AttributeTypes.PXDimensionSelectorAttribute; AttributeInformation attributeInformation = new AttributeInformation(pxContext); var dacPropertiesWithForeignKeys = from dacProperty in dacSemanticModel.DacProperties where !dacProperty.Attributes.IsDefaultOrEmpty && dacProperty.BoundType == BoundType.DbBound && //only Bound FKs should work correctly dacProperty.Attributes.Any(attribute => IsForeignKeyAttribute(attribute)) orderby dacProperty.DeclarationOrder ascending select dacProperty; return(dacPropertiesWithForeignKeys.ToList()); //----------------------------------------Local Function---------------------------------------------------------------- bool IsForeignKeyAttribute(AttributeInfo attribute) { const string selectorAttributeProperty = "SelectorAttribute"; bool isDerivedFromOrAggregateForeignKeyAttribute = foreignKeyAttributes.Exists( foreignKeyAttribute => attributeInformation.IsAttributeDerivedFromClass(attribute.AttributeType, foreignKeyAttribute)); if (isDerivedFromOrAggregateForeignKeyAttribute) { return(true); } var selectorAttributeMembers = attribute.AttributeType.GetBaseTypesAndThis() .SelectMany(type => type.GetMembers(selectorAttributeProperty)); var selectorAttributeCandidateMemberTypes = from type in attribute.AttributeType.GetBaseTypesAndThis() .TakeWhile(attrType => attrType != pxContext.AttributeTypes.PXEventSubscriberAttribute) from member in type.GetMembers(selectorAttributeProperty) select member switch { IPropertySymbol property => property.Type, IFieldSymbol field => field.Type, _ => null }; return(selectorAttributeCandidateMemberTypes .Any(memberType => memberType != null && (attributeInformation.IsAttributeDerivedFromClass(memberType, selectorAttribute) || attributeInformation.IsAttributeDerivedFromClass(memberType, dimensionSelectorAttribute)))); } }