public StateManager(HostAnalyzerManager analyzerManager) { _analyzerManager = analyzerManager; _hostStates = new HostStates(this); _projectStates = new ProjectStates(this); }
public DiagnosticIncrementalAnalyzer(DiagnosticAnalyzerService owner, int correlationId, Workspace workspace, HostAnalyzerManager hostAnalyzerManager, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource) : base(workspace, hostDiagnosticUpdateSource) { _correlationId = correlationId; _owner = owner; _hostAnalyzerManager = hostAnalyzerManager; }
public override async Task SynchronizeWithBuildAsync(Project project, ImmutableArray <DiagnosticData> diagnostics) { if (!PreferBuildErrors(project.Solution.Workspace)) { // prefer live errors over build errors return; } using (var poolObject = SharedPools.Default <HashSet <string> >().GetPooledObject()) { var lookup = CreateDiagnosticIdLookup(diagnostics); foreach (var stateSet in _stateManager.GetStateSets(project)) { var descriptors = HostAnalyzerManager.GetDiagnosticDescriptors(stateSet.Analyzer); var liveDiagnostics = ConvertToLiveDiagnostics(lookup, descriptors, poolObject.Object); // we are using Default so that things like LB can't use cached information var projectTextVersion = VersionStamp.Default; var semanticVersion = await project.GetDependentSemanticVersionAsync(CancellationToken.None).ConfigureAwait(false); var state = stateSet.GetState(StateType.Project); var existingDiagnostics = await state.TryGetExistingDataAsync(project, CancellationToken.None).ConfigureAwait(false); var mergedDiagnostics = MergeDiagnostics(liveDiagnostics, GetExistingDiagnostics(existingDiagnostics)); await state.PersistAsync(project, new AnalysisData(projectTextVersion, semanticVersion, mergedDiagnostics), CancellationToken.None).ConfigureAwait(false); RaiseDiagnosticsUpdated(StateType.Project, project.Id, stateSet, new SolutionArgument(project), mergedDiagnostics); } } }
private static ImmutableDictionary <DiagnosticAnalyzer, StateSet> CreateAnalyzerMap( HostAnalyzerManager analyzerManager, string language, IEnumerable <ImmutableArray <DiagnosticAnalyzer> > analyzerCollection) { var compilerAnalyzer = analyzerManager.GetCompilerDiagnosticAnalyzer(language); var builder = ImmutableDictionary.CreateBuilder <DiagnosticAnalyzer, StateSet>(); foreach (var analyzers in analyzerCollection) { foreach (var analyzer in analyzers) { // TODO: // #1, all de -duplication should move to HostAnalyzerManager // #2, not sure whether de-duplication of analyzer itself makes sense. this can only happen // if user deliberately put same analyzer twice. if (builder.ContainsKey(analyzer)) { continue; } var buildToolName = analyzer == compilerAnalyzer ? PredefinedBuildTools.Live : GetBuildToolName(analyzerManager, language, analyzer); builder.Add(analyzer, new StateSet(language, analyzer, buildToolName)); } } return(builder.ToImmutable()); }
private ImmutableDictionary <DiagnosticAnalyzer, DiagnosticAnalysisResult> 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, 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 group = liveDiagnostics.GroupBy(d => d.DocumentId); var result = new DiagnosticAnalysisResult( 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(), fromBuild: true); builder.Add(stateSet.Analyzer, result); } return(builder.ToImmutable()); } }
private bool ShouldRunForFullProject(DiagnosticAnalyzer analyzer, Project project) { // PERF: Don't query descriptors for compiler analyzer, always execute it. if (HostAnalyzerManager.IsCompilerDiagnosticAnalyzer(project.Language, analyzer)) { return(true); } return(Owner.ShouldRunForFullProject(analyzer, project)); }
private bool ShouldRunForFullProject(DiagnosticAnalyzer analyzer, Project project) { // PERF: Don't query descriptors for compiler analyzer, always execute it. if (HostAnalyzerManager.IsCompilerDiagnosticAnalyzer(project.Language, analyzer)) { return(true); } // most of analyzers, number of descriptor is quite small, so this should be cheap. return(Owner.GetDiagnosticDescriptors(analyzer).Any(d => GetEffectiveSeverity(d, project.CompilationOptions) != ReportDiagnostic.Hidden)); }
private static string GetErrorSourceName(HostAnalyzerManager analyzerManager, string language, DiagnosticAnalyzer analyzer) { var packageName = analyzerManager.GetDiagnosticAnalyzerPackageName(language, analyzer); if (packageName == null) { return(null); } return($"{analyzer.GetAnalyzerAssemblyName()} [{packageName}]"); }
public DiagnosticIncrementalAnalyzer( DiagnosticAnalyzerService owner, int correlationId, Workspace workspace, HostAnalyzerManager analyzerManager, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource) : base(owner, workspace, analyzerManager, hostDiagnosticUpdateSource) { _correlationId = correlationId; _memberRangeMap = new MemberRangeMap(); _executor = new AnalyzerExecutor(this); _stateManager = new StateManager(analyzerManager); _stateManager.ProjectAnalyzerReferenceChanged += OnProjectAnalyzerReferenceChanged; }
public DiagnosticIncrementalAnalyzer( DiagnosticAnalyzerService owner, int correlationId, Workspace workspace, HostAnalyzerManager analyzerManager, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource) : base(owner, workspace, analyzerManager, hostDiagnosticUpdateSource) { _correlationId = correlationId; _memberRangeMap = new MemberRangeMap(); _executor = new AnalyzerExecutor(this); _eventQueue = new SimpleTaskQueue(TaskScheduler.Default); _stateManager = new StateManager(analyzerManager); _stateManager.ProjectAnalyzerReferenceChanged += OnProjectAnalyzerReferenceChanged; }
public DiagnosticIncrementalAnalyzer( DiagnosticAnalyzerService owner, int correlationId, Workspace workspace, HostAnalyzerManager analyzerManager, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource) : base(owner, workspace, analyzerManager, hostDiagnosticUpdateSource) { _correlationId = correlationId; _memberRangeMap = new MemberRangeMap(); _executor = new AnalyzerExecutor(this); _eventQueue = new SimpleTaskQueue(TaskScheduler.Default); _stateManager = new StateManager(analyzerManager); _stateManager.ProjectAnalyzerReferenceChanged += OnProjectAnalyzerReferenceChanged; _solutionCrawlerAnalysisState = new SolutionCrawlerAnalysisState(analyzerManager); }
private static string GetBuildToolName(HostAnalyzerManager analyzerManager, string language, DiagnosticAnalyzer analyzer) { var packageName = analyzerManager.GetDiagnosticAnalyzerPackageName(language, analyzer); if (packageName == null) { return(null); } if (packageName == RoslynLanguageServices) { return(PredefinedBuildTools.Live); } return($"{analyzer.GetAnalyzerAssemblyName()} [{packageName}]"); }
public DiagnosticIncrementalAnalyzer( DiagnosticAnalyzerService owner, int correlationId, Workspace workspace, HostAnalyzerManager hostAnalyzerManager, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource) : base(owner, workspace, hostAnalyzerManager, hostDiagnosticUpdateSource) { _correlationId = correlationId; _stateManager = new StateManager(hostAnalyzerManager); _stateManager.ProjectAnalyzerReferenceChanged += OnProjectAnalyzerReferenceChanged; _executor = new Executor(this); _compilationManager = new CompilationManager(this); }
public DiagnosticAnalyzerMap(HostAnalyzerManager analyzerManager, string language, ImmutableDictionary <DiagnosticAnalyzer, StateSet> analyzerMap) { // hold directly on to compiler analyzer _compilerAnalyzer = analyzerManager.GetCompilerDiagnosticAnalyzer(language); // in test case, we might not have the compiler analyzer. if (_compilerAnalyzer == null) { _map = analyzerMap; return; } _compilerStateSet = analyzerMap[_compilerAnalyzer]; // hold rest of analyzers _map = analyzerMap.Remove(_compilerAnalyzer); }
public DiagnosticAnalyzerMap(HostAnalyzerManager analyzerManager, string language, ImmutableDictionary<DiagnosticAnalyzer, StateSet> analyzerMap) { // hold directly on to compiler analyzer _compilerAnalyzer = analyzerManager.GetCompilerDiagnosticAnalyzer(language); // in test case, we might not have the compiler analyzer. if (_compilerAnalyzer == null) { _map = analyzerMap; return; } _compilerStateSet = analyzerMap[_compilerAnalyzer]; // hold rest of analyzers _map = analyzerMap.Remove(_compilerAnalyzer); }
public DiagnosticAnalyzerMap(HostAnalyzerManager analyzerManager, string language, ImmutableDictionary <DiagnosticAnalyzer, StateSet> analyzerMap) { _map = analyzerMap; var compilerAnalyzer = analyzerManager.GetCompilerDiagnosticAnalyzer(language); // in test case, we might not have the compiler analyzer. if (compilerAnalyzer != null) { // hold onto stateSet for compiler analyzer _compilerStateSet = analyzerMap[compilerAnalyzer]; } // order statesets // order will be in this order // BuiltIn Compiler Analyzer (C#/VB) < Regular DiagnosticAnalyzers < Document/ProjectDiagnosticAnalyzers _orderedSet = _map.Values.OrderBy(PriorityComparison).ToImmutableArray(); }
public override async Task SynchronizeWithBuildAsync(Document document, ImmutableArray <DiagnosticData> diagnostics) { var workspace = document.Project.Solution.Workspace; if (!PreferBuildErrors(workspace)) { // prefer live errors over build errors return; } // check whether, for opened documents, we want to prefer live diagnostics if (PreferLiveErrorsOnOpenedFiles(workspace) && workspace.IsDocumentOpen(document.Id)) { // enqueue re-analysis of open documents. this.Owner.Reanalyze(workspace, documentIds: SpecializedCollections.SingletonEnumerable(document.Id)); return; } using (var poolObject = SharedPools.Default <HashSet <string> >().GetPooledObject()) { var lookup = CreateDiagnosticIdLookup(diagnostics); foreach (var stateSet in _stateManager.GetStateSets(document.Project)) { // we are using Default so that things like LB can't use cached information var textVersion = VersionStamp.Default; var semanticVersion = await document.Project.GetDependentSemanticVersionAsync(CancellationToken.None).ConfigureAwait(false); // clear document and project live errors await PersistAndReportAsync(stateSet, StateType.Project, document, textVersion, semanticVersion, ImmutableArray <DiagnosticData> .Empty).ConfigureAwait(false); await PersistAndReportAsync(stateSet, StateType.Syntax, document, textVersion, semanticVersion, ImmutableArray <DiagnosticData> .Empty).ConfigureAwait(false); var descriptors = HostAnalyzerManager.GetDiagnosticDescriptors(stateSet.Analyzer); var liveDiagnostics = ConvertToLiveDiagnostics(lookup, descriptors, poolObject.Object); // REVIEW: for now, we are putting build error in document state rather than creating its own state. // reason is so that live error can take over it as soon as possible // this also means there can be slight race where it will clean up eventually. if live analysis runs for syntax but didn't run // for document yet, then we can have duplicated entries in the error list until live analysis catch. await PersistAndReportAsync(stateSet, StateType.Document, document, textVersion, semanticVersion, liveDiagnostics).ConfigureAwait(false); } } }
private async Task <ImmutableArray <DiagnosticData> > GetProjectDiagnosticsAsync(Project project, CancellationToken cancellationToken) { if (project == null) { return(ImmutableArray <DiagnosticData> .Empty); } var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var analyzers = HostAnalyzerManager.CreateDiagnosticAnalyzers(project); var compilationWithAnalyzer = compilation.WithAnalyzers(analyzers, project.AnalyzerOptions, cancellationToken); // REVIEW: this API is a bit strange. // if getting diagnostic is cancelled, it has to create new compilation and do everything from scretch again? var dxs = GetDiagnosticData(project, await compilationWithAnalyzer.GetAnalyzerDiagnosticsAsync().ConfigureAwait(false)).ToImmutableArrayOrEmpty(); return(dxs); }
private bool SupportAnalysisKind(DiagnosticAnalyzer analyzer, string language, AnalysisKind kind) { // compiler diagnostic analyzer always support all kinds if (HostAnalyzerManager.IsCompilerDiagnosticAnalyzer(language, analyzer)) { return(true); } switch (kind) { case AnalysisKind.Syntax: return(analyzer.SupportsSyntaxDiagnosticAnalysis()); case AnalysisKind.Semantic: return(analyzer.SupportsSemanticDiagnosticAnalysis()); default: return(Contract.FailWithReturn <bool>("shouldn't reach here")); } }
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 DiagnosticIncrementalAnalyzer( DiagnosticAnalyzerService owner, int correlationId, Workspace workspace, HostAnalyzerManager hostAnalyzerManager, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource) { Contract.ThrowIfNull(owner); Owner = owner; Workspace = workspace; HostAnalyzerManager = hostAnalyzerManager; HostDiagnosticUpdateSource = hostDiagnosticUpdateSource; DiagnosticLogAggregator = new DiagnosticLogAggregator(owner); _correlationId = correlationId; _stateManager = new StateManager(hostAnalyzerManager); _stateManager.ProjectAnalyzerReferenceChanged += OnProjectAnalyzerReferenceChanged; _executor = new Executor(this); _compilationManager = new CompilationManager(this); }
private bool IsCandidateForFullSolutionAnalysis(DiagnosticAnalyzer analyzer, Project project) { // PERF: Don't query descriptors for compiler analyzer, always execute it. if (HostAnalyzerManager.IsCompilerDiagnosticAnalyzer(project.Language, analyzer)) { return(true); } if (analyzer.IsBuiltInAnalyzer()) { // always return true for builtin analyzer. we can't use // descriptor check since many builtin analyzer always return // hidden descriptor regardless what descriptor it actually // return on runtime. they do this so that they can control // severity through option page rather than rule set editor. // this is special behavior only ide analyzer can do. we hope // once we support editorconfig fully, third party can use this // ability as well and we can remove this kind special treatment on builtin // analyzer. return(true); } return(Owner.HasNonHiddenDescriptor(analyzer, project)); }
private static string GetBuildToolName(HostAnalyzerManager analyzerManager, string language, DiagnosticAnalyzer analyzer) { var packageName = analyzerManager.GetDiagnosticAnalyzerPackageName(language, analyzer); if (packageName == null) { return null; } if (packageName == RoslynLanguageServices) { return PredefinedBuildTools.Live; } return $"{analyzer.GetAnalyzerAssemblyName()} [{packageName}]"; }
private static ImmutableDictionary<DiagnosticAnalyzer, StateSet> CreateAnalyzerMap( HostAnalyzerManager analyzerManager, string language, IEnumerable<ImmutableArray<DiagnosticAnalyzer>> analyzerCollection) { var compilerAnalyzer = analyzerManager.GetCompilerDiagnosticAnalyzer(language); var builder = ImmutableDictionary.CreateBuilder<DiagnosticAnalyzer, StateSet>(); foreach (var analyzers in analyzerCollection) { foreach (var analyzer in analyzers) { // TODO: // #1, all de -duplication should move to HostAnalyzerManager // #2, not sure whether de-duplication of analyzer itself makes sense. this can only happen // if user deliberately put same analyzer twice. if (builder.ContainsKey(analyzer)) { continue; } var buildToolName = analyzer == compilerAnalyzer ? PredefinedBuildTools.Live : GetBuildToolName(analyzerManager, language, analyzer); builder.Add(analyzer, new StateSet(language, analyzer, buildToolName)); } } return builder.ToImmutable(); }
public SolutionCrawlerAnalysisState(HostAnalyzerManager hostAnalyzerManager) { _projectAnalysisStateCache = new ConditionalWeakTable <Project, ProjectAnalysisState>(); _hostAnalyzerManager = hostAnalyzerManager; _lastCacheCleanupTime = DateTime.UtcNow; }
public DiagnosticIncrementalAnalyzer(DiagnosticAnalyzerService owner, int correlationId, Workspace workspace, HostAnalyzerManager hostAnalyzerManager, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource) : base(owner, workspace, hostAnalyzerManager, hostDiagnosticUpdateSource) { _correlationId = correlationId; }
private static string GetErrorSourceName(HostAnalyzerManager analyzerManager, string language, DiagnosticAnalyzer analyzer) { var packageName = analyzerManager.GetDiagnosticAnalyzerPackageName(language, analyzer); if (packageName == null) { return null; } return $"{analyzer.GetAnalyzerAssemblyName()} [{packageName}]"; }
public SolutionCrawlerAnalysisState(HostAnalyzerManager hostAnalyzerManager) { _projectAnalysisStateCache = new ConditionalWeakTable<Project, ProjectAnalysisState>(); _hostAnalyzerManager = hostAnalyzerManager; _lastCacheCleanupTime = DateTime.UtcNow; }