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(); } }
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)); }
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); } }
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); } } }
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); } }
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()); }
public void CalculateClassMetrics(ProjectAnalysisData prj, ClassMetrics clsMetrics, ClassAnalysisData cls, SemanticModel sclsmodel) { DepthOfInheritanceRule depthOfInheritance = new DepthOfInheritanceRule(sclsmodel); clsMetrics.DOI = depthOfInheritance.Calculate(cls.ClassDeclarationSyntax); }
private static void AnalyzeMethod(ProjectAnalysisData prj, ClassAnalysisData cls, ClassMetrics clsMetrics) { MethodMetricscalculator mmc = new MethodMetricscalculator(); mmc.Calculate(prj, clsMetrics, cls); }
private static void CalculateClassMetrics(ProjectAnalysisData prj, ClassMetrics clsMetrics, ClassAnalysisData cls) { ClassMetricscalculator calculate = new ClassMetricscalculator(); calculate.Calculate(prj, clsMetrics, cls); }
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); }