예제 #1
0
        public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            Trace.WriteLine("RegisterCodeFixesAsync");
            try
            {
                var diagnostic = context.Diagnostics.First();

                var cacheItem = EFRoslynTheoremCache.Get(diagnostic.Properties["CacheId"]);

                context.RegisterCodeFix(
                    CodeAction.Create(
                        title: title,
                        createChangedSolution: cancellationToken =>
                        FixEFModelAsync(context.Document.Project, cacheItem.Compilation,
                                        cacheItem.EFRoslynTheorem.ClassAssumptions, cacheItem.EFRoslynTheorem.PropertyAssumptions, cacheItem.ObjectTheoremResult,
                                        cancellationToken),
                        equivalenceKey: title),
                    diagnostic);

                return(Task.CompletedTask);
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.ToString());
                throw;
            }
        }
        private void AnalyzeCompilation(CompilationAnalysisContext context)
        {
            Trace.WriteLine("AnalyzeCompilation");

            try
            {
                INamedTypeSymbol dbContextTypeSymbol;
                IEnumerable <INamedTypeSymbol> entityTypeSymbols = SymbolHelper.GetAllEntityTypesFromDbContext(context.Compilation, out dbContextTypeSymbol);
                if (!entityTypeSymbols.Any())
                {
                    return;
                }

                var allTypeSymbols   = context.Compilation.GetSymbolsWithName(s => !s.EndsWith("DbContext"), SymbolFilter.Type).Cast <INamedTypeSymbol>();
                var allMemberSymbols = allTypeSymbols.SelectMany(t => t.GetMembers().Where(m => m.Kind == SymbolKind.Property));
                Trace.WriteLine("Class count: " + allTypeSymbols.Count());
                Trace.WriteLine("Property count: " + allMemberSymbols.Count());

                var efRoslynTheorem = new EFRoslynTheorem();
                var result          = efRoslynTheorem.Solve(entityTypeSymbols);
                if (result.Status == Status.Unsatisfiable)
                {
                    var classAssumptions    = efRoslynTheorem.ClassAssumptions.ToList();
                    var propertyAssumptions = efRoslynTheorem.PropertyAssumptions.OrderBy(pa => pa.Rank).ToList();

                    do
                    {
                        result = TryToRemoveWrongAssumption(efRoslynTheorem, result, classAssumptions, propertyAssumptions);
                    } while (result != null && result.Status != Status.Satisfiable);

                    if (result == null || result.Status != Status.Satisfiable)
                    {
                        var diagnostic2 = Diagnostic.Create(UnsatisfiableRule, dbContextTypeSymbol.Locations[0], dbContextTypeSymbol.Name);
                        Trace.WriteLine("ReportDiagnostic " + diagnostic2.Descriptor.Id);
                        context.ReportDiagnostic(diagnostic2);
                        return;
                    }

                    var cacheId = EFRoslynTheoremCache.Add(context.Compilation, efRoslynTheorem, result);

                    var props = ImmutableDictionary.Create <string, string>();
                    props = props.Add("CacheId", cacheId);

                    var diagnostic = Diagnostic.Create(SatisfiableRule, dbContextTypeSymbol.Locations[0], props, dbContextTypeSymbol.Name);
                    Trace.WriteLine("ReportDiagnostic " + diagnostic.Descriptor.Id);
                    context.ReportDiagnostic(diagnostic);
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.ToString());
                throw;
            }
        }