private ImmutableDictionary<DiagnosticAnalyzer, AnalysisResult> CreateAnalysisResults(
            Project project, ImmutableArray<StateSet> stateSets, ProjectAnalysisData oldAnalysisData, ImmutableArray<DiagnosticData> diagnostics)
        {
            using (var poolObject = SharedPools.Default<HashSet<string>>().GetPooledObject())
            {
                // we can't distinguish locals and non locals from build diagnostics nor determine right snapshot version for the build.
                // so we put everything in as semantic local with default version. this lets us to replace those to live diagnostics when needed easily.
                var version = VersionStamp.Default;
                var lookup = diagnostics.ToLookup(d => d.Id);

                var builder = ImmutableDictionary.CreateBuilder<DiagnosticAnalyzer, AnalysisResult>();
                foreach (var stateSet in stateSets)
                {
                    var descriptors = HostAnalyzerManager.GetDiagnosticDescriptors(stateSet.Analyzer);
                    var liveDiagnostics = MergeDiagnostics(ConvertToLiveDiagnostics(lookup, descriptors, poolObject.Object), GetDiagnostics(oldAnalysisData.GetResult(stateSet.Analyzer)));

                    var group = liveDiagnostics.GroupBy(d => d.DocumentId);
                    var result = new AnalysisResult(
                        project.Id,
                        version,
                        documentIds: group.Where(g => g.Key != null).Select(g => g.Key).ToImmutableHashSet(),
                        syntaxLocals: ImmutableDictionary<DocumentId, ImmutableArray<DiagnosticData>>.Empty,
                        semanticLocals: group.Where(g => g.Key != null).ToImmutableDictionary(g => g.Key, g => g.ToImmutableArray()),
                        nonLocals: ImmutableDictionary<DocumentId, ImmutableArray<DiagnosticData>>.Empty,
                        others: group.Where(g => g.Key == null).SelectMany(g => g).ToImmutableArrayOrEmpty());

                    builder.Add(stateSet.Analyzer, result);
                }

                return builder.ToImmutable();
            }
        }
Ejemplo n.º 2
0
        private async Task <ProjectAnalysisData> CreateProjectAnalysisDataAsync(Project project, ImmutableArray <StateSet> stateSets, ImmutableArray <DiagnosticData> diagnostics)
        {
            // we always load data sicne we don't know right version.
            var avoidLoadingData = false;
            var oldAnalysisData  = await ProjectAnalysisData.CreateAsync(project, stateSets, avoidLoadingData, CancellationToken.None).ConfigureAwait(false);

            var newResult = CreateAnalysisResults(project, stateSets, oldAnalysisData, diagnostics);

            return(new ProjectAnalysisData(project.Id, VersionStamp.Default, oldAnalysisData.Result, newResult));
        }
Ejemplo n.º 3
0
        public async Task InitializeSynchronizationStateWithBuildAsync(Solution solution, CancellationToken cancellationToken)
        {
            foreach (var project in solution.Projects)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var stateSets = _stateManager.CreateBuildOnlyProjectStateSet(project);
                _ = await ProjectAnalysisData.CreateAsync(PersistentStorageService, project, stateSets, avoidLoadingData : false, cancellationToken).ConfigureAwait(false);
            }
        }
Ejemplo n.º 4
0
 public void AnalyzeClass(ProjectAnalysisData prj, ProjectMetrics metrics)
 {
     foreach (var cls in prj.Classes)
     {
         ClassMetrics clsMetrics = new ClassMetrics();
         CalculateClassMetrics(prj, clsMetrics, cls);
         AnalyzeMethod(prj, cls, clsMetrics);
         AnalyzePropertie(prj, cls, clsMetrics);
         metrics.ClassMetrics.Add(clsMetrics);
     }
 }
        public void Calculate(ProjectAnalysisData prj, ClassMetrics clsMetrics, ClassAnalysisData cls)
        {
            clsMetrics.Classname     = cls.ClassDeclarationSyntax.Identifier.ValueText;
            clsMetrics.Classdocpath  = cls.ClassDeclarationSyntax.SyntaxTree.FilePath;
            clsMetrics.Namespacename = cls.Namespace.Namespacedeclaration.Name.ToString();
            SemanticModel sclsmodel = prj.CompiledProject.GetSemanticModel(cls.ClassDeclarationSyntax.SyntaxTree);

            foreach (var rule in _rulesList)
            {
                rule.CalculateClassMetrics(prj, clsMetrics, cls, sclsmodel);
            }
        }
        public async Task SynchronizeWithBuildAsync(ImmutableDictionary <ProjectId, ImmutableArray <DiagnosticData> > buildDiagnostics)
        {
            var options = Workspace.Options;

            using (Logger.LogBlock(FunctionId.DiagnosticIncrementalAnalyzer_SynchronizeWithBuildAsync, LogSynchronizeWithBuild, options, buildDiagnostics, CancellationToken.None))
            {
                DebugVerifyDiagnosticLocations(buildDiagnostics);

                if (!PreferBuildErrors(options))
                {
                    // prefer live errors over build errors
                    return;
                }

                var solution = Workspace.CurrentSolution;

                foreach (var(projectId, diagnostics) in buildDiagnostics)
                {
                    var project = solution.GetProject(projectId);
                    if (project == null)
                    {
                        continue;
                    }

                    // REVIEW: do build diagnostics include suppressed diagnostics?
                    var stateSets = _stateManager.CreateBuildOnlyProjectStateSet(project);

                    // we load data since we don't know right version.
                    var oldAnalysisData = await ProjectAnalysisData.CreateAsync(PersistentStorageService, project, stateSets, avoidLoadingData : false, CancellationToken.None).ConfigureAwait(false);

                    var newResult = CreateAnalysisResults(project, stateSets, oldAnalysisData, diagnostics);

                    foreach (var stateSet in stateSets)
                    {
                        var state  = stateSet.GetOrCreateProjectState(project.Id);
                        var result = GetResultOrEmpty(newResult, stateSet.Analyzer, project.Id, VersionStamp.Default);
                        await state.SaveAsync(PersistentStorageService, project, result).ConfigureAwait(false);
                    }

                    // REVIEW: this won't handle active files. might need to tweak it later.
                    RaiseProjectDiagnosticsIfNeeded(project, stateSets, oldAnalysisData.Result, newResult);
                }

                // if we have updated errors, refresh open files
                if (buildDiagnostics.Count > 0 && PreferLiveErrorsOnOpenedFiles(options))
                {
                    // enqueue re-analysis of open documents.
                    AnalyzerService.Reanalyze(Workspace, documentIds: Workspace.GetOpenDocumentIds(), highPriority: true);
                }
            }
        }
Ejemplo n.º 7
0
        public void Calculate(ProjectAnalysisData prj, ClassMetrics clsMetrics, ClassAnalysisData cls)
        {
            SemanticModel smtdmodel = prj.CompiledProject.GetSemanticModel(cls.ClassDeclarationSyntax.SyntaxTree);

            foreach (var mtd in cls.Methods)
            {
                MethodMetrics mtdMetrics = new MethodMetrics();
                foreach (var rule in _rulesList)
                {
                    rule.CalculateMethodMetrics(prj, clsMetrics, cls, mtdMetrics, mtd.MethodDeclarationSyntax, smtdmodel);
                }
                clsMetrics.MethodMetricses.Add(mtdMetrics);
            }
        }
Ejemplo n.º 8
0
        private async Task <ProjectAnalysisData> GetProjectAnalysisDataAsync(
            CompilationWithAnalyzers?compilationWithAnalyzers, Project project, IEnumerable <StateSet> stateSets, bool forceAnalyzerRun, CancellationToken cancellationToken)
        {
            using (Logger.LogBlock(FunctionId.Diagnostics_ProjectDiagnostic, GetProjectLogMessage, project, stateSets, cancellationToken))
            {
                try
                {
                    // PERF: We need to flip this to false when we do actual diffing.
                    var avoidLoadingData = true;
                    var version          = await GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false);

                    var existingData = await ProjectAnalysisData.CreateAsync(PersistentStorageService, project, stateSets, avoidLoadingData, cancellationToken).ConfigureAwait(false);

                    // We can't return here if we have open file only analyzers since saved data for open file only analyzer
                    // is incomplete -- it only contains info on open files rather than whole project.
                    if (existingData.Version == version && !CompilationHasOpenFileOnlyAnalyzers(compilationWithAnalyzers, project.Solution.Options))
                    {
                        return(existingData);
                    }

                    // PERF: Check whether we want to analyze this project or not.
                    if (!FullAnalysisEnabled(project, forceAnalyzerRun))
                    {
                        Logger.Log(FunctionId.Diagnostics_ProjectDiagnostic, p => $"FSA off ({p.FilePath ?? p.Name})", project);

                        return(new ProjectAnalysisData(project.Id, VersionStamp.Default, existingData.Result, ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResult> .Empty));
                    }

                    var result = await ComputeDiagnosticsAsync(compilationWithAnalyzers, project, stateSets, forceAnalyzerRun, existingData.Result, cancellationToken).ConfigureAwait(false);

                    // If project is not loaded successfully, get rid of any semantic errors from compiler analyzer.
                    // Note: In the past when project was not loaded successfully we did not run any analyzers on the project.
                    // Now we run analyzers but filter out some information. So on such projects, there will be some perf degradation.
                    result = await RemoveCompilerSemanticErrorsIfProjectNotLoadedAsync(result, project, cancellationToken).ConfigureAwait(false);

                    return(new ProjectAnalysisData(project.Id, version, existingData.Result, result));
                }
                catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
                {
                    throw ExceptionUtilities.Unreachable;
                }
            }
        }
            /// <summary>
            /// Return all diagnostics that belong to given project for the given StateSets (analyzers) either from cache or by calculating them
            /// </summary>
            public async Task <ProjectAnalysisData> GetProjectAnalysisDataAsync(
                CompilationWithAnalyzers analyzerDriverOpt, Project project, IEnumerable <StateSet> stateSets, bool forceAnalyzerRun, CancellationToken cancellationToken)
            {
                using (Logger.LogBlock(FunctionId.Diagnostics_ProjectDiagnostic, GetProjectLogMessage, project, stateSets, cancellationToken))
                {
                    try
                    {
                        // PERF: we need to flip this to false when we do actual diffing.
                        var avoidLoadingData = true;
                        var version          = await GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false);

                        var existingData = await ProjectAnalysisData.CreateAsync(project, stateSets, avoidLoadingData, cancellationToken).ConfigureAwait(false);

                        // we can't return here if we have open file only analyzers sine saved data for open file only analyzer
                        // is wrong. (since it only contains info on open files rather than whole project)
                        if (existingData.Version == version && !analyzerDriverOpt.ContainsOpenFileOnlyAnalyzers(project.Solution.Workspace))
                        {
                            return(existingData);
                        }

                        // perf optimization. check whether we want to analyze this project or not.
                        if (!FullAnalysisEnabled(project, forceAnalyzerRun))
                        {
                            Logger.Log(FunctionId.Diagnostics_ProjectDiagnostic, p => $"FSA off ({p.FilePath ?? p.Name})", project);

                            return(new ProjectAnalysisData(project.Id, VersionStamp.Default, existingData.Result, ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResult> .Empty));
                        }

                        var result = await ComputeDiagnosticsAsync(analyzerDriverOpt, project, stateSets, forceAnalyzerRun, existingData.Result, cancellationToken).ConfigureAwait(false);

                        // if project is not loaded successfully, get rid of any semantic errors from compiler analyzer
                        // * NOTE * previously when project is not loaded successfully, we actually dropped doing anything on the project, but now
                        //          we do everything but filter out some information. so on such projects, there will be some perf degradation.
                        result = await FilterOutCompilerSemanticErrorsIfNeccessaryAsync(project, result, cancellationToken).ConfigureAwait(false);

                        return(new ProjectAnalysisData(project.Id, version, existingData.Result, result));
                    }
                    catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
                    {
                        throw ExceptionUtilities.Unreachable;
                    }
                }
            }
        private ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResult> CreateAnalysisResults(
            Project project, ImmutableArray <StateSet> stateSets, ProjectAnalysisData oldAnalysisData, ImmutableArray <DiagnosticData> diagnostics)
        {
            using var poolObject = SharedPools.Default <HashSet <string> >().GetPooledObject();

            var lookup = diagnostics.ToLookup(d => d.Id);

            var builder = ImmutableDictionary.CreateBuilder <DiagnosticAnalyzer, DiagnosticAnalysisResult>();

            foreach (var stateSet in stateSets)
            {
                var descriptors     = HostAnalyzerManager.GetDiagnosticDescriptors(stateSet.Analyzer);
                var liveDiagnostics = MergeDiagnostics(ConvertToLiveDiagnostics(lookup, descriptors, poolObject.Object), GetDiagnostics(oldAnalysisData.GetResult(stateSet.Analyzer)));

                var result = DiagnosticAnalysisResult.CreateFromBuild(project, liveDiagnostics);

                builder.Add(stateSet.Analyzer, result);
            }

            return(builder.ToImmutable());
        }
Ejemplo n.º 11
0
        public void CalculateClassMetrics(ProjectAnalysisData prj, ClassMetrics clsMetrics, ClassAnalysisData cls, SemanticModel sclsmodel)
        {
            DepthOfInheritanceRule depthOfInheritance = new DepthOfInheritanceRule(sclsmodel);

            clsMetrics.DOI = depthOfInheritance.Calculate(cls.ClassDeclarationSyntax);
        }
Ejemplo n.º 12
0
        private static void AnalyzeMethod(ProjectAnalysisData prj, ClassAnalysisData cls, ClassMetrics clsMetrics)
        {
            MethodMetricscalculator mmc = new MethodMetricscalculator();

            mmc.Calculate(prj, clsMetrics, cls);
        }
Ejemplo n.º 13
0
        private static void CalculateClassMetrics(ProjectAnalysisData prj, ClassMetrics clsMetrics, ClassAnalysisData cls)
        {
            ClassMetricscalculator calculate = new ClassMetricscalculator();

            calculate.Calculate(prj, clsMetrics, cls);
        }
Ejemplo n.º 14
0
 public void CalculateMethodMetrics(ProjectAnalysisData prj, ClassMetrics clsMetrics, ClassAnalysisData cls,
                                    MethodMetrics mtdMetrics, MethodDeclarationSyntax mtd, SemanticModel sclsmodel)
 {
     Rule.MethodparametersRule mtdprmrule = new Rule.MethodparametersRule();
     mtdMetrics.Methodparameters = mtdprmrule.GetMethodparametersCount(mtd);
 }